Вопрос

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

// header
int func(int i);

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

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

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

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

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

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

// 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' для параметров функции

Пример того, когда полезны параметры с постоянным значением:

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
}
Это было полезно?

Решение

Мой взгляд на это:

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

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

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

   /* ... */
}

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

Другие советы

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

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

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

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

Итак, функция fillArray с сигнатурой, подобной этой:

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

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

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

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

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

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

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

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

Невозможно изменить объект const

Но изменение '*i' (т.е.* i = 3;) означает, что вы меняете не значение 'i', а значение адреса, на который указывает 'i'

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

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top