Объявление ссылки на объект и оператор присваивания - PullRequest
11 голосов
/ 31 июля 2011

Мне кажется, что этот вопрос достаточно простой, чтобы где-то быть там, но я не могу найти ответ на него.

Предположим, у меня есть этот код:

//class member function
std::map< std::string, std::string > myMap;

const std::map< std::string, std::string >& bar()
{
   return myMap;
}

void myFunc( std::map< std::string, std::string >& foo1 )
{
   foo1 = bar();
   std::map< std::string, std::string >& foo2 = bar();
}

Насколько я понимаю, если я начну использовать foo2, так как foo2 является ссылкой на тот же экземпляр, что и то, что возвращает bar (), все, что я делаю с foo2, будет отражено в myMap. Но как насчет foo1? Получает ли foo1 копию myMap или он также указывает на тот же экземпляр, что и то, что возвращает bar ()? Стандартная библиотека c ++ говорит, что оператор присваивания для std :: map будет копировать элементы, но означает ли это, что оператор присваивания в действительности не вызывается в объявлении foo2?

Спасибо!

Ответы [ 2 ]

16 голосов
/ 31 июля 2011

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

foo1 = bar();
std::map< std::string, std::string >& foo2 = bar();

первая строка вызывает std::map::operator= объекта, который был передан в качестве параметра myFunc.После этого foo1 stills ссылается на тот же объект - но его значение (например, какие элементы он содержит) может быть очень хорошо изменено.

Обратите внимание, что вторая строка - , а не задание, если когда-либо было сомнение, что это было в вашем уме.Это инициализация.Так как тип возвращаемого столбца на самом деле std::map<std::string, std::string> const&, он не может быть привязан к std::map<std::string, std::string>&, поэтому это ошибка компиляции.


Чтобы развернуть «философскую» сторону, ссылки на C ++разработан, чтобы быть максимально прозрачным и на самом деле не существует в виде объектов.Это использует стандартный термин C ++ для термина (он не связан с ООП): это означает, что, например, ссылочные типы имеют , а не размер.Вместо этого sizeof(T&) == sizeof(T).Аналогично, ссылки не имеют адресов, и невозможно сформировать указатель или ссылку на ссылку: если дано int& ref = i;, то &ref == &i.

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

0 голосов
/ 31 июля 2011

Строка

foo1 = bar();

создает копию (потому что это то, что делает оператор присваивания map).

...