Re[13]: Возвращение константной ссылки
От: Masterkent  
Дата: 04.01.12 23:47
Оценка: 23 (2)
c-smile:

CS>Это всё понятно. Вопрос состоит в том когда будет вызван деструктор обоих строк.


CS>В C++03 s2 есть ссылка на убитый объект — ctor и dtor в той же "строке".

CS>В C++11 s2 есть ссылка на валидный объект — его dtor на выходе из scope.

Нет, s2 в обоих случаях указывает на временный объект, чьё время жизни совпадает со временем жизни ссылки. Разница между C++03 и C++11 состоит в том, что в рамках C++03 ссылка могла связываться как непосредственно с исходным объектом, так и с созданной копией исходного объекта (причём конструктор, выполняющий копирование, должен быть доступен независимо от того, какой из этих двух способов избирает реализация), а в рамках C++11 создание копии в данном контексте не разрешается и требования наличия конструктора, выполняющего копирование или перемещение, нет.

CS>В месте объявления ссылки не всегда очевидно как эта ссылка получена.


CS>
CS>const std::string& s1 = foo(); // foo() -> std:string
CS>const std::string& s2 = bar(); // bar() -> const std:string& 
CS>


CS>s1 и s2 здесь явно демонстрируют разное поведение (в плане вызова деструкторов).


Так оно и задумано. Если я ничего не забыл, правила C++11 — 12.2/5 касаются только следующих случаев:

1) temporary object, с которым связывается ссылка, создаётся в контексте её инициализации (см. 8.5.3/5/2/2, 8.5.4/3/5);

2) ссылка связывается непосредственно с тем объектом, который обозначает инициализирующее её выражение, и это выражение является prvalue.

В стандарте это довольно невнятно описано. Есть соотвествующая core issue (Issue 1299. “Temporary objects” vs “temporary expressions” — увы, пока без публично доступного описания) с запросом на уточнение правил.

В примере выше foo() — это prvalue, а bar() — lvalue (glvalue). glvalue не считается за temporary, даже если в действительности оно ссылается на temporary object. Ну а prvalue классового типа считается за temporary (за исключением случаев, предусмотренных в 5.2.2/11).
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.