Когда использовать const и ссылку на const в аргументах функции?
При написании функции C++ с аргументами, которые ей передаются, из моего понимания всегда следует использовать const, если вы можете гарантировать, что объект не будет изменен, или указатель const, если указатель не будет изменен.
Когда еще рекомендуется эта практика?
Когда бы вы использовали константную ссылку и каковы преимущества по сравнению с простой передачей ее через указатель, например?
Как насчет этого void MyObject::Somefunc(const std::string& mystring)
Какой смысл иметь константную строку, если строка на самом деле уже является неизменным объектом?
4 ответа
К сожалению , вопрос о том, нужно ли добавлять const, неправильный.
Сравните неконстантную ссылку с передачей неконстантного указателя
void modifies(T ¶m);
void modifies(T *param);
Этот случай в основном о стиле: хотите, чтобы звонок выглядел как call(obj)
или же call(&obj)
? Однако есть два момента, где разница имеет значение. Если вы хотите иметь возможность передавать значение NULL, вы должны использовать указатель. И если вы перегружаете операторы, вы не можете использовать указатель вместо этого.
Сравните const ref со значением
void doesnt_modify(T const ¶m);
void doesnt_modify(T param);
Это интересный случай. Практическое правило гласит, что типы "дешевого копирования" передаются по значению - обычно это небольшие типы (но не всегда), в то время как другие передаются по const ref. Однако, если вам нужно сделать копию внутри вашей функции независимо, вы должны передать по значению. (Да, это раскрывает некоторые детали реализации. C'est le C++.)
Сравните константный указатель с немодифицируемой плюс перегрузкой
void optional(T const *param=0);
// vs
void optional();
void optional(T const ¶m); // or optional(T param)
Это связано с немодифицирующим случаем выше, за исключением того, что передача параметра является необязательной. Здесь наименьшая разница между всеми тремя ситуациями, так что выбирайте, что облегчит вашу жизнь. Конечно, значение по умолчанию для неконстантного указателя зависит от вас.
Const by value - это деталь реализации
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
Общее правило, используйте const
когда это возможно, и опускайте его только при необходимости. const
может позволить компилятору оптимизировать процесс и помочь вашим коллегам понять, как ваш код предназначен для использования (и компилятор обнаружит возможное неправильное использование).
Что касается вашего примера, строки не являются неизменяемыми в C++. Если вы вручаете неconst
ссылка на строку в функции, функция может изменить ее. C++ не имеет встроенной в язык концепции неизменности, ее можно эмулировать только с помощью инкапсуляции и const
(который никогда не будет пуленепробиваемым, хотя).
Подумав над комментариями @Eamons и прочтя некоторые вещи, я согласен с тем, что оптимизация не является основной причиной использования const
, Основная причина в том, чтобы иметь правильный код.
Вопросы основаны на некоторых неправильных предположениях, поэтому не имеют большого значения.
std::string
не моделирует неизменные строковые значения. Он моделирует изменяемые значения.
Нет такой вещи, как "константная ссылка". Есть ссылки на const
объекты. Различие тонкое, но важное.
Верхний уровень const
аргумент функции имеет смысл только для реализации функции, а не для чистого объявления (где он игнорируется компилятором). Это ничего не говорит звонящему. Это только ограничение по реализации. Например int const
в значительной степени бессмысленно в качестве типа аргумента в чистом объявлении функции. Тем не менее const
в std::string const&
это не верхний уровень.
Передача по ссылке на const
избегает неэффективного копирования данных. Как правило, для аргумента, передающего данные в функцию, вы передаете небольшие элементы (такие как int
) по стоимости, и потенциально более крупные предметы по ссылке на const
, В машинном коде ссылка на const
может быть оптимизирован или может быть реализован как указатель. Например, в 32-битной Windows int
4 байта и указатель 4 байта. Так что тип аргумента int const&
не уменьшит копирование данных, но может с помощью простого компилятора ввести дополнительное косвенное обращение, что означает небольшую неэффективность - отсюда и небольшое / большое различие.
Ура & hth.,
Основное преимущество константной ссылки над константным указателем заключается в следующем: ясно, что параметр является обязательным и не может быть NULL. И наоборот, если я вижу константный указатель, я сразу же предполагаю, что причиной того, что он не является ссылкой, является то, что параметр может быть НЕДЕЙСТВИТЕЛЕН.