Когда использовать const и ссылку на const в аргументах функции? - PullRequest
20 голосов
/ 19 октября 2010

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

Когда еще рекомендуется эта практика?

Когда бы вы использовали константную ссылку и каковы преимущества по сравнению с простой передачей ее, например, через указатель?

Как насчет этого void MyObject::Somefunc(const std::string& mystring) Какой смысл иметь константную строку, если строка фактически уже является неизменным объектом?

Ответы [ 4 ]

39 голосов
/ 19 октября 2010

Спрашивать, добавлять ли const - это неправильный вопрос, , к сожалению.

Сравнить неконстантную ссылку с передачей неконстантного указателя

void modifies(T &param);
void modifies(T *param);

Это дело в основном о стиле: хотите, чтобы звонок выглядел как call(obj) или call(&obj)? Однако есть два момента, где разница имеет значение. Если вы хотите иметь возможность передавать значение NULL, вы должны использовать указатель. А если вы перегружаете операторы, вы не можете вместо этого использовать указатель.

Сравните const ref со значением

void doesnt_modify(T const &param);
void doesnt_modify(T param);

Это интересный случай. Практическое правило гласит, что типы «дешевого копирования» передаются по значению - обычно это небольшие типы (но не всегда), в то время как другие передаются по const ref. Тем не менее, если вам нужно сделать копию внутри вашей функции независимо, вы должны передать значение . (Да, это раскрывает некоторые детали реализации. C'est le C ++. )

Сравнить константный указатель с немодифицируемой плюс перегрузкой

void optional(T const *param=0);
// vs
void optional();
void optional(T const &param); // or optional(T param)

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

Константа по значению является подробностью реализации

void f(T);
void f(T const);

Эти объявления на самом деле являются точно такой же функцией! При передаче по значению const является просто деталью реализации. Попробуйте:

void f(int);
void f(int const) {/*implements above function, not an overload*/}

typedef void C(int const);
typedef void NC(int);
NC *nc = &f;  // nc is a function pointer
C *c = nc;  // C and NC are identical types
4 голосов
/ 19 октября 2010

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

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

Подумав @Eamons прокомментируйте и прочитав некоторые вещиЯ согласен, что оптимизация не является основной причиной использования const.Основная причина - иметь правильный код.

3 голосов
/ 19 октября 2010

Вопросы основаны на некоторых неверных допущениях, поэтому не имеют смысла.

std::string не моделирует неизменные строковые значения.Он моделирует изменяемые значения.

Не существует такой вещи, как "константная ссылка".Есть ссылки на const объекты.Различие тонкое, но важное.

Верхний уровень const для аргумента функции имеет смысл только для реализации функции, а не для чистого объявления (где оно игнорируется компилятором).Это ничего не говорит звонящему.Это только ограничение по реализации.Например, int const практически бессмыслен как тип аргумента в чистом объявлении функции.Однако const в std::string const& не является верхним уровнем.

Передача по ссылке на const позволяет избежать неэффективного копирования данных.Как правило, для аргумента, передающего данные в функцию, вы передаете небольшие элементы (например, int) по значению и потенциально более крупные элементы по ссылке на const.В машинном коде ссылка на const может быть оптимизирована или может быть реализована в виде указателя.Например, в 32-битной Windows int составляет 4 байта, а указатель - 4 байта.Таким образом, тип аргумента int const& не уменьшит копирование данных, но может с помощью простого компилятора ввести дополнительную косвенность, что означает небольшую неэффективность - отсюда и небольшое / большое различие.

Cheers & hth.

0 голосов
/ 19 октября 2010

Основное преимущество константной ссылки над константным указателем заключается в следующем: ясно, что параметр является обязательным и не может быть NULL.И наоборот, если я вижу константный указатель, я немедленно предполагаю, что причина, по которой он не является ссылкой, заключается в том, что параметр может иметь значение NULL.

...