2012-01-03 3 views
83

Какова цель const в этом?Цель возврата значения const?

const Object myFunc(){ 
    return myObject; 
} 

Я только начал читать Эффективное использование C++ и пункт 3 сторонников этого и поиск Google поднимает подобные предложения, но и контрпримеры. Я не вижу, как использование const здесь было бы предпочтительнее. Предполагая, что возвращение по значению желательно, я не вижу причин для защиты возвращаемого значения. Приведенный пример, почему это может быть полезно, - это предотвращение непреднамеренных отклонений bool от возвращаемого значения. Фактическая проблема заключается в том, что неявные команды bool должны быть предотвращены с явным ключевым словом.

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

Что получается при использовании функции const здесь и когда было бы предпочтительнее?

EDIT: Измените пример арифметики на любую функцию, которая изменяет объект, который вы хотите выполнить перед назначением.

+1

Да, вы можете выполнить арифметику с объектами const, потому что арифметические операторы должны быть const, а также возвращать объекты const –

ответ

87

В гипотетической ситуации, когда вы могли бы выполнить потенциально дорогостоящую неконстантную операцию на объекте, возвращаясь по константной стоимости предотвращает случайный вызов эта операция выполняется на временной основе. Представьте себе, что + вернулся неконстантное значением, и вы могли бы написать:

(a + b).expensive(); 

В возрасте C++ 11, однако, настоятельно рекомендуются возвращать значения, как неконстантные, так что вы можете взять полные преимущество ссылок rvalue, которые имеют смысл только на непостоянных значениях r.

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

+0

Ну, Herb Sutter [рекомендуется возвращать значения const] (http://books.google.com/books?id = 58rZvOSuheEC & lpg = PA179 & ots = L_LgismXMo & dq = sutter% 20return% 20const% 20value & pg = PA179 # v = onepage & q & f = false) для не-примитивных типов, но я думаю, вы правы, что совет устарел сейчас. –

+10

@FredLarson: Да, в 14-летней книге: -S –

+0

. Ответы подразумевают, что возвращение по const-value означает const &&, но действительно ли это правда ?! например VS13 позволяет мне связывать int && var = с функцией, которая возвращает const int. «Результат вызова функции, тип возврата которой не является ссылкой, является значением prvalue». –

32

It's prettypointless для возврата значения const из функции.

Это difficult, чтобы получить его, чтобы иметь какой-либо эффект на ваш код:

const int foo() { 
    return 3; 
} 

int main() { 
    int x = foo(); // copies happily 
    x = 4; 
} 

and:

const int foo() { 
    return 3; 
} 

int main() { 
    foo() = 4; // not valid anyway for built-in types 
} 

// error: lvalue required as left operand of assignment 

Хотя you can notice if the return type is a user-defined type:

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 не является параметром шаблона, вы этого не делаете.

+0

. Обратите внимание, что второй пример вызывает только ошибку для встроенных типов. – Xeo

+0

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

+1

@ ИвайлоТосков: Вся необходимая разработка - это пример, в частности комментарий, в котором говорится, что «копирует счастливо». Рассмотрим 'const int x = 4; int y = x ;, что также отлично. –

-2

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

Хотя любой оптимизатор, скорее всего, оптимизировать его в любом случае ...

+0

Но он возвращает «Объект». –

+0

Нечего оптимизировать, константа - это механизм безопасности во время компиляции. –

+0

А, я неправильно читаю его как Object * ... –

-3

myObject может быть указателем. «Const» защищает значение, указанное myObject.

+3

На самом деле, нет. 'Object const *' не 'Object * const'. –

3

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

myFunc() = Object(...); 

Это будет работать хорошо, если myFunc возвращаемой ссылки, но это почти наверняка ошибка при возврате по значению (и, вероятно, не будет пойман компилятор). Конечно, в C++ 11 с его rvalues ​​это соглашение не имеет такого большого смысла, как раньше, поскольку объект const нельзя перенести, так что это может иметь довольно сильные последствия для производительности.

+0

Это не объясняет 'const'. –

+0

@ Никол Болас: Как он не объясняет const? Пример кода во время компиляции, если тип возвращаемого значения - 'Object', но нет, если он является' const Object' – Grizzly

+0

Предположительно вы имеете в виду «в C++ 11 с его _xvalues_»? (Знайте, что _xvalues_ и _prvalues_ являются _rvalues_, но его _xvalues_, которые являются новыми для C++ 11, которые являются важным отличием.) –

1

C++ 11 делает его весьма полезным для объектов только для перемещения. Например:

const std::unique_ptr<T> myFunc(); 

unique_ptr представляет собой тип, который не может быть скопирован; его можно только перемещать. Но вы не можете позвонить по номеру std::move по номеру const. Таким образом, единственный способ сохранить это с const& или const&&:

const std::unique_ptr<T> &ptr = myFunc(); 

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

Таким образом, обеспечивает, что указатель не хранится долговременно. Это позволяет создать специализированную версию unique_ptr, которая на деле не удаляет память. Таким образом, функция может возвращать указатель, зная, что пользователь не может его хранить в любом месте.

Конечно, это также затрудняет возврат вызывающего абонента. Таким образом, есть недостатки.

+1

Простите, но я должен сделать это во втором - вы можете * сохранить переменную long -term - особенно в глобальной или функции-статической или потоковой локальной переменной. Во-вторых, даже если rvalue привязано к локальной ссылке, это не означает, что эта функция не будет работать до конца программы. В-третьих, сделать жизнь звонящего сложнее - это очень глупая просьба. И, в-четвертых, создание уникальной_папки, которая не удаляет ее, - вам просто нужно убедиться, что плательщик переживет его указатель (например, глобальный). Ваше устройство не помогает с этой гарантией. – jpalecek

+0

Подождите Ват? Вы храните ссылку на временное, которое немедленно уничтожается? Это даже компилируется? –

+2

@EmilyL. Постоянная ссылка на временное может продлить срок ее службы, см. Https://herbsutter.com/2008/01/01/gotw-88-a-candidate-for-the-most-important-const/ – tomjakubowski