Последствия использования амперсанда перед именем функции в C ++? - PullRequest
10 голосов
/ 23 декабря 2011

Приведенный пример:

inline string &GetLabel( ) {
        return m_Label;
};

Где m_Label - переменная-член частного класса.

Как мне кажется, я понимаю, что эта функция будет возвращать ссылку на переменную m_Label. Каковы будут последствия использования этого в моей программе, и будет ли лучше просто вернуть значение вместо ссылки? Спасибо!

Ответы [ 5 ]

12 голосов
/ 23 декабря 2011

Амперсанд находится не перед именем функции, а после возвращаемого типа. возвращает ссылку на string.

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

inline const string& GetLabel() const
{
    return m_Label;
}

Лучшее из обоих миров. Вы избегаете копирования, но абоненты не могут изменить ваш объект.

9 голосов
/ 23 декабря 2011

Возвращает ссылку на приватного участника.

Во многих случаях это желательно, но следует позаботиться о них.

ИМО, как правило, возвращатькопия внутреннего объекта, который не является целочисленным типом, из соображений общей производительности.Да, я знаю, преждевременная оптимизация не очень хороша, но на самом деле это не оптимизация, это просто хорошая практика производительности, которая позволяет вызывающей стороне определять влияние на производительность;если ему нужна копия, она может просто не объявлять переменную, которой она присваивается, в качестве ссылки.

Здесь я использую 2 общих правила:

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

inline const string& GetLabel() const{ return m_Label; }

2) Вызывающая сторона никогда не должна хранить ссылку, возвращенную из метода класса, она должнаиспользоваться только локально, если родительский объект гарантированно находится в области видимости.

Если по какой-то причине вам требуется, чтобы вызывающие объекты могли хранить ссылку на ваши внутренние объекты, используйте вместо этого интеллектуальные указатели.

2 голосов
/ 23 декабря 2011

Одним из следствий является то, что если разрушающий объект разрушен, ссылка становится недействительной:

Object* o = new Object;
string& label = o->GetLabel();
delete o;
// label becomes a dangling reference here.

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

2 голосов
/ 23 декабря 2011

Возврат ссылки означает, что вызывающий код может изменить значение вашей переменной-члена после вашего возврата.Это очень опасно, если только вы не предполагали, что это произойдет.

Лучше будет const ссылка или возврат по значению (без &).

1 голос
/ 23 декабря 2011

Вы правы. Это ссылка на строковый член.

Подразумевается, что если бы вызывающий объект должен был присвоить значение или иным образом изменить возвращаемую строку, он бы также изменил переменную-член. Если это не так, вы можете вернуть копию по значению, чтобы избежать нарушения инкапсуляции.

...