Использование const для параметров функции - PullRequest
347 голосов
/ 23 сентября 2008

Как далеко вы идете с const? Вы просто делаете функции const, когда это необходимо, или вы используете всю свинью и используете ее везде? Например, представьте себе простой мутатор, который принимает один логический параметр:

void SetValue(const bool b) { my_val_ = b; }

Это const действительно полезно? Лично я предпочитаю использовать его широко, включая параметры, но в этом случае мне интересно, стоит ли это делать?

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

.h file

void func(int n, long l);

.cpp file

void func(const int n, const long l)

Есть ли причина для этого? Это кажется мне немного необычным.

Ответы [ 30 ]

7 голосов
/ 24 июля 2012

Если вы используете операторы ->* или .*, это обязательно.

Это мешает вам написать что-то вроде

void foo(Bar *p) { if (++p->*member > 0) { ... } }

, что я почти сделал прямо сейчас, и который, вероятно, не делает то, что вы собираетесь.

То, что я намеревался сказать, было

void foo(Bar *p) { if (++(p->*member) > 0) { ... } }

и если бы я положил const между Bar * и p, компилятор сказал бы мне это.

5 голосов
/ 23 сентября 2008

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

5 голосов
/ 23 сентября 2008

Маркировка значений параметров «const» - определенно субъективная вещь.

Однако на самом деле я предпочитаю отмечать значения параметров const, как в вашем примере.

void func(const int n, const long l) { /* ... */ }

Значение для меня ясно указывает на то, что значения параметров функции никогда не изменяются функцией. Они будут иметь то же значение в начале, что и в конце. Для меня это часть поддержания стиля очень функционального программирования.

Для короткой функции, возможно, является пустой тратой времени / пространства, чтобы иметь там "const", поскольку обычно довольно очевидно, что аргументы не модифицируются функцией.

Однако для более крупной функции это форма документации по реализации, и она обеспечивается компилятором.

Я могу быть уверен, что если я сделаю какое-то вычисление с 'n' и 'l', я смогу реорганизовать / переместить это вычисление, не боясь получить другой результат, потому что я пропустил место, где один или оба изменены.

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

4 голосов
/ 23 сентября 2008

const не имеет смысла, когда аргумент передается по значению, так как вы не будете изменять объект вызывающего.

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

Наконец, функция, которая не изменяет текущий объект (this), может и, вероятно, должна быть объявлена ​​как const. Пример ниже:

int SomeClass::GetValue() const {return m_internalValue;}

Это обещание не изменять объект, к которому применяется этот вызов. Другими словами, вы можете позвонить:

const SomeClass* pSomeClass;
pSomeClass->GetValue();

Если функция не константная, это приведет к предупреждению компилятора.

3 голосов
/ 04 апреля 2015

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

2 голосов
/ 23 сентября 2008

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

Насколько я знаю, компилятор может очень хорошо увидеть параметр константного значения и сказать: "Эй, эта функция все равно не изменяет его, поэтому я могу передать по ссылке и сохранить некоторые тактовые циклы". Я не думаю, что это когда-либо сделало бы такую ​​вещь, так как это изменяет сигнатуру функции, но это имеет значение. Может быть, он выполняет какие-то другие манипуляции со стеком или что-то в этом роде ... Дело в том, что я не знаю, но я знаю, что попытка быть умнее компилятора только приводит к тому, что мне стыдно.

В C ++ есть дополнительный багаж с идеей правильности, поэтому он становится еще более важным.

2 голосов
/ 23 сентября 2008

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

Что действительно важно, так это пометить методы как const, если они не изменяют свой экземпляр. Делайте это по ходу дела, потому что в противном случае вы можете получить либо много const_cast <>, либо вы можете обнаружить, что маркировка метода const требует изменения большого количества кода, потому что он вызывает другие методы, которые должны быть отмечены как const.

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

2 голосов
/ 23 сентября 2008

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

2 голосов
/ 23 сентября 2008

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

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

2 голосов
/ 06 мая 2009

Об оптимизации компилятора: http://www.gotw.ca/gotw/081.htm

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...