Цель возврата значения const?
Какова цель const в этом?
const Object myFunc(){
return myObject;
}
Я только начал читать Effective С++, а пункт 3 защищает это, и поиск в Google поднимает аналогичные предложения, но также и контрпримеры. Я не вижу, как использование const здесь было бы предпочтительнее. Предполагая, что возвращение по значению желательно, я не вижу причин для защиты возвращаемого значения. Приведенный пример, почему это может быть полезно, - это предотвращение непреднамеренных отклонений bool от возвращаемого значения. Фактическая проблема заключается в том, что неявные команды bool должны быть предотвращены с явным ключевым словом.
Использование const здесь предотвращает использование временных объектов без назначения. Поэтому я не мог выполнять арифметические выражения с этими объектами. Кажется, что когда-либо случалось, что неназванный const полезен.
Что получается при использовании const здесь и когда было бы предпочтительнее?
EDIT: измените пример арифметики на любую функцию, которая модифицирует объект, который вы хотите выполнить перед назначением.
Ответы
Ответ 1
В гипотетической ситуации, когда вы могли бы выполнить потенциально дорогостоящую неконстантную операцию над объектом, возврат константы-const предотвращает случайное обращение этой операции к временному. Представьте, что +
возвратил неконстантное значение, и вы могли бы написать:
(a + b).expensive();
Однако в возрасте С++ 11 настоятельно рекомендуется возвращать значения как неконстантные, чтобы вы могли в полной мере использовать ссылки rvalue, которые имеют смысл только при неконстантных значениях r.
Таким образом, существует обоснование для этой практики, но оно существенно устарело.
Ответ 2
Это довольно бессмысленно, чтобы вернуть значение const
из функции.
Это трудно, чтобы заставить его повлиять на ваш код:
const int foo() {
return 3;
}
int main() {
int x = foo(); // copies happily
x = 4;
}
и:
const int foo() {
return 3;
}
int main() {
foo() = 4; // not valid anyway for built-in types
}
// error: lvalue required as left operand of assignment
Хотя вы можете заметить, если тип возвращаемого значения является определяемым пользователем типом:
struct T {};
const T foo() {
return T();
}
int main() {
foo() = T();
}
// error: passing ‘const T’ as ‘this’ argument of ‘T& T::operator=(const T&)’ discards qualifiers
сомнительно, имеет ли это какое-либо преимущество для всех.
Возврат ссылки отличается, но если Object
не является некоторым параметром шаблона, вы этого не делаете.
Ответ 3
Он гарантирует, что возвращаемый объект (который является RValue в этой точке) не может быть изменен. Это гарантирует, что пользователь не может так думать:
myFunc() = Object(...);
Это хорошо работает, если myFunc
возвращается ссылкой, но почти наверняка является ошибкой при возврате значения (и, вероятно, не будет уловлен компилятором). Конечно, в С++ 11 с его rvalues это соглашение не имеет такого большого смысла, как раньше, поскольку объект const не может быть перенесен, поэтому это может иметь довольно сильные последствия для производительности.
Ответ 4
С++ 11 делает его весьма полезным для объектов только для перемещения. Например:
const std::unique_ptr<T> myFunc();
unique_ptr
- тип, который нельзя скопировать; его можно только перемещать. Но вы не можете вызвать std::move
для типа const
. Поэтому единственный способ сохранить это - с помощью const&
или const&&
:
const std::unique_ptr<T> &ptr = myFunc();
Так как это a const unique_ptr
, его нельзя перенести. Не может быть скопировано. Это означает, что очень трудно фактически сохранить это в любом месте в долгосрочной перспективе. Вы можете поместить его в стек. Но сделать его членом класса невозможно (без вызова поведения undefined).
Таким образом, можно гарантировать, что указатель не будет храниться долговременно. Это позволяет создать специализированную версию unique_ptr
, которая на самом деле не удаляет память. Таким образом, функция может возвращать указатель, зная, что пользователь не может его хранить в любом месте.
Конечно, это также затрудняет возврат вызывающего объекта. Таким образом, есть недостатки.
Ответ 5
Он может использоваться как функция-обертка для возврата ссылки на закрытый тип данных констант. Например, в связанном списке есть хвост и голова констант, и если вы хотите определить, является ли node хвостом или головой node, вы можете сравнить его со значением, возвращаемым этой функцией.
Хотя любой оптимизатор, скорее всего, оптимизирует его в любом случае...
Ответ 6
myObject может быть указателем. "Const" защищает значение, указанное myObject.