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).