Цель возврата значения 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.