const <type>& foo () против <type>foo () - PullRequest
3 голосов
/ 12 января 2010

В не шаблонном классе, есть ли причина отдавать предпочтение сигнатурам возвращаемых функций в виде const <type>& foo(); вместо <type> foo();? Где <type> является внутренним типом. А что если <type> является объектом класса / структуры?

Также интересует, имеет ли значение значение const : const <type>& foo() const; до <type> foo() const;

например. в не шаблонном классе, не шаблонная функция:

const int& foo() const { return member_variable_; }

по сравнению

int foo() const { return member_variable_; }

Ответы [ 5 ]

3 голосов
/ 12 января 2010

Для примитивных типов просто возвращайте по значению. Нет причины возвращать примитив по константной ссылке.

Для не примитивных типов это зависит.

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

Если возвращаемое значение является членом класса, у вас есть выбор.

Возврат по константной ссылке позволяет избежать копий, что может быть преимуществом в производительности. Однако он связывает ваш интерфейс с реализацией, то есть член данных и возвращаемое значение должны быть одного типа. Это также менее безопасно, потому что вызывающая сторона может сохранять ссылку дольше, чем время жизни объекта, например:

const X& x = y->foo();
delete y;
// use x, oops!

Возврат по значению включает одну или две копии, в зависимости от того, можете ли вы воспользоваться преимуществами оптимизации возвращаемого значения (что, вероятно, для простых методов get (), таких как этот). Кроме того, копии объектов, использующие конструкторы копирования по умолчанию, могут копироваться более эффективно (подумайте: компилятор может просто запоминать данные).

Рекомендация: начните с возврата по значению и переключитесь на возврат по константной ссылке только после определения того, что этот вызов / копия, как известно, является проблемой производительности.

Наконец, другой альтернативой является возврат по параметру, который может быть полезен для более сложных объектов (например, строки):

void foo(X& return_val) { return_val = member_variable_; }

или

void foo(X* return_val) {
    assert(return_val != 0);
    *return_val = member_variable_;
}
0 голосов
/ 12 января 2010

Если тип является внутренним типом, передача константных ссылок не улучшит производительность и может ухудшить ее, а также будет менее безопасным; лучше отдать предпочтение прохождению и возврату по значению. Я не большой специалист по ASM, но, насколько я понимаю, под возвратом ссылки подразумевается, что значение не может быть сохранено в регистре, так как ему нужен адрес для возврата, и, таким образом, можно отключить некоторые полезные оптимизации; Хотя я не уверен в этом.

Если это класс или структура, это зависит от времени жизни значения; если он является локальным для функции, он не может быть возвращен, в противном случае, если он является членом класса, я предпочитаю тип const & return, поскольку он может предложить лучшую производительность, избегая конструкторов копирования. (мнения расходятся, так как по значению считается более безопасным). Это также избавляет вас от необходимости создавать конструкторы копирования или использовать потенциально злые значения по умолчанию, что приятно.

0 голосов
/ 12 января 2010

Все зависит от того, что именно вы хотите сделать.

Если вы хотите вернуть ссылку на объект, который будет использоваться кодом пользователя, тогда:

<type>& foo()  { ... }

Если вы хотите вернуть ссылку на объект, но только для чтения, разрешив только доступ к константным функциям этого типа объекта, то:

const <type>& foo() { ... }

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

<type>& foo() const { ... }

Если вы хотите, чтобы не возвращать ссылку на объект, но только для чтения, предоставляя доступ только к const-функциям этого типа объекта, и событие, если экземпляр класса используется только для чтения (как const), тогда:

const <type>& foo() const { ... }

Просто чтобы добавить предупреждение: не возвращайте ссылки на переменные функции, они не существуют вне функции ...

0 голосов
/ 12 января 2010
const <type>& foo();

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

<type> foo();

Возвращает новую копию ресурса <type>. Это означает, что копия сделана. Это хорошо для простых данных или в тех случаях, когда значения могут быть общими, и вы хотите убедиться, что каждый экземпляр <type> является отдельным - не общим, как некоторая строка или целое число.

0 голосов
/ 12 января 2010

Если вам нужно вернуть значение, вы ДОЛЖНЫ вернуть значение - константная ссылка не является приемлемой заменой. Но я подозреваю, что вы спрашиваете о чем-то вроде этого:

struct A {
   X x;
    ...
   X f1() { return x; }
   const X & f2() { return x; }
};

Я никогда не придумал для этого надежного руководства.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...