Последствия использования амперсанда перед именем функции в C++?

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

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

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

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

5 ответов


он возвращает ссылку на собственный член.

есть много случаев, когда это желательно, но следует проявлять некоторую осторожность.

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

есть 2 общих эмпирических правила, которые я использую здесь:

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

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

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

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


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

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

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

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


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

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


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

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

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


вы правы. Это ссылка на элемент строки.

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