Const правильность для значений параметров - PullRequest
25 голосов
/ 12 ноября 2009

Я знаю, что мало вопросов о правильности констант, когда утверждается, что для объявления функции и ее определения не нужно согласовывать значения параметров. Это связано с тем, что постоянство значения параметра имеет значение только внутри функции. Это нормально:

// header
int func(int i);

// cpp
int func(const int i) {
    return i;
}

Это действительно лучший способ? Потому что я никогда не видел, чтобы кто-нибудь делал это. Я видел эту цитату (не уверен в источнике) в других местах, где это обсуждалось:

"На самом деле, для компилятора сигнатура функции одинакова независимо от того, включена эта константа перед параметром значения или нет."

"Избегайте передачи параметров const по значению в объявлениях функций. При этом оставьте параметр const в том же определении функции, если он не будет изменен."

Во втором абзаце говорится, что не следует указывать const в объявлении Я предполагаю, что это потому, что постоянство параметра-значения не имеет смысла как часть определения интерфейса. Это деталь реализации.

Исходя из этой рекомендации, также рекомендуется ли для значений указателя параметры указателя? (Это не имеет смысла для параметра ссылки, поскольку вы не можете переназначить ссылку.)

// header
int func1(int* i);
int func2(int* i);

// cpp
int func1(int* i) {
    int x = 0;

    *i = 3; // compiles without error
    i = &x; // compiles without error

    return *i;
}
int func2(int* const i) {
    int x = 0;

    *i = 3; // compiles without error
    i = &x; // compile error

    return *i;
}

Резюме: Создание параметров-значений полезно для выявления некоторых логических ошибок. Это лучшая практика? Вы идете до крайности, оставляя const из файла заголовка? Это так же полезно, чтобы константные значения указателя? Почему или почему нет?

Некоторые ссылки:

C ++ const ключевое слово - использовать свободно? Использование const для параметров функции

Пример использования параметров const:

bool are_ints_equal(const int i, const int j) {
    if (i = j) { // without the consts this would compile without error
        return true;
    } else {
        return false;
    }
    // return i = j; // I know it can be shortened
}

Ответы [ 7 ]

10 голосов
/ 12 ноября 2009

Я много раз читал, что создание значений параметров в функции const - плохая вещь, потому что это не нужно.

Однако я иногда нахожу это полезным для проверки того, что моя реализация не выполняет то, что я не намерен (как в примере в конце вашего вопроса).

Таким образом, хотя это может не увеличивать ценность для вызывающей стороны, оно иногда добавляет мне небольшую ценность как средство реализации и ничего не отнимает у вызывающей стороны. Поэтому я не вижу вреда, используя его.

Например, я могу реализовывать функцию C, которая принимает пару указателей на буфер - указатель на начало и указатель на конец. Я собираюсь поместить данные в буфер, но хочу убедиться, что я не переполняю конец. Так что внутри функции есть код, который будет увеличивать указатель, когда я добавляю в него данные. Сделав указатель на конец буфера параметром const, я не буду кодировать ошибку, которая случайно увеличивает указатель конечной границы вместо указателя, который я действительно должен увеличивать.

Итак, функция fillArray с такой подписью:

size_t fillArray( data_t* pStart, data_t* const pEnd);

предотвратит случайное увеличение pEnd, когда я действительно хочу увеличить pStart. Это не так уж и много, но я уверен, что все, кто программировал на C в течение какого-то периода времени, сталкивались с такой ошибкой.

8 голосов
/ 12 ноября 2009

Мое мнение:

Это неплохая идея, но проблема незначительна, и ваша энергия может быть лучше потрачена на другие вещи.

В своем вопросе вы предоставили хороший пример того, когда он может поймать ошибку, но иногда вы также в конечном итоге делаете что-то вроде этого:

void foo(const int count ...)
{
   int temp = count;  // can't modify count, so we need a copy of it
   ++temp;

   /* ... */
}

Плюсы и минусы незначительны в любом случае.

1 голос
/ 12 ноября 2009

К сожалению, некоторые компиляторы (я смотрю на вас, Sun CC!) Неправильно различают аргументы, объявленные как const, и аргументы, не объявленные так, и вы можете получить ошибки о неопределенных функциях.

0 голосов
/ 23 марта 2017

Мы все время от времени должны распутывать чужой код C ++. И что чей-то код на C ++ является полным беспорядком по определению: D.

Итак, первое, что я всегда делаю, чтобы расшифровать его (локальный и глобальный поток данных), это ставить const в каждом определении переменной, пока компилятор не пожалуется. Это также означает аргументы-значения, соответствующие определенным константам, и это действительно помогает избежать переменных, которые были изменены в середине функции, и я не заметил этого ...

Так что я действительно ценю, когда кто-то еще имеет const везде (включая значения параметров): D

0 голосов
/ 12 апреля 2016

Если присутствует ключевое слово const; это означает, что значение 'i' (тип const) не может быть изменено. Если значение 'i' изменено внутри функции foo, компилятор выдаст ошибку: "

Невозможно изменить константный объект

Но изменение «* i» (т. Е. * I = 3;) означает, что вы не изменяете значение «i», а значение адреса, указанного «i»

На самом деле, функция const подходит для больших объектов, которые не должны изменяться функцией.

0 голосов
/ 12 ноября 2009

Я думаю, это зависит от вашего личного стиля.

Это не добавляет и не вычитает того, что клиенты могут передать вашей функции. По сути, это как утверждение времени компиляции. Если это поможет вам узнать, что ценность не изменится, продолжайте и сделайте это, но я не вижу большой причины для других делать это.

Одна из причин, по которой я мог бы этого не делать, заключается в том, что постоянство параметра value - это деталь реализации, о которой ваши клиенты не должны знать. Если вы позже (намеренно) измените свою функцию, чтобы она действительно изменила это значение, вам потребуется изменить сигнатуру вашей функции, что заставит ваших клиентов перекомпилироваться.

Это похоже на то, почему некоторые люди рекомендуют не использовать общедоступные виртуальные методы (функции виртуальности - это детали реализации, которые должны быть скрыты от клиентов), но я не в этом конкретном лагере.

0 голосов
/ 12 ноября 2009

Мне нравится постоянная корректность в таких ситуациях:
void foo(const Bar &b) //I know b cannot be changed<br> {<br> //do something with b<br> }

Это позволяет мне использовать b, не опасаясь его изменения, но мне не нужно платить за конструктор копирования.

...