Я розумію, що в C ++ 11, коли ви повертаєте локальну змінну з функції за значенням, компілятору дозволено трактувати цю змінну як посилання на значення r і "перемістити" її з функції, щоб повернути її (якщо Натомість RVO / NRVO не відбувається).
Моє запитання: чи не може це порушити існуючий код?
Розглянемо наступний код:
#include <iostream>
#include <string>
struct bar
{
bar(const std::string& str) : _str(str) {}
bar(const bar&) = delete;
bar(bar&& other) : _str(std::move(other._str)) {other._str = "Stolen";}
void print() {std::cout << _str << std::endl;}
std::string _str;
};
struct foo
{
foo(bar& b) : _b(b) {}
~foo() {_b.print();}
bar& _b;
};
bar foobar()
{
bar b("Hello, World!");
foo f(b);
return std::move(b);
}
int main()
{
foobar();
return EXIT_SUCCESS;
}
Мої думки полягали в тому, що деструктор локального об'єкта може посилатися на об'єкт, який неявно переміщується, і тому несподівано побачить «порожній» об’єкт. Я намагався перевірити це (див http://ideone.com/ZURoeT ), але я отримав «правильний» результат без явного std::move
дюйма foobar()
. Я здогадуюсь, що це було пов’язано з NRVO, але я не намагався змінити код, щоб відключити це.
Чи я правдивий, що це перетворення (спричинення виходу з функції) відбувається неявно і може порушити існуючий код?
ОНОВЛЕННЯ Ось приклад, який ілюструє те, про що я говорю. Наступні два посилання для одного і того ж коду. http://ideone.com/4GFIRu - C ++ 03 http://ideone.com/FcL2Xj - C ++ 11
Якщо ви подивитеся на вихід, то це інакше.
Отже, я думаю, це питання зараз стає, чи враховувалося це при додаванні неявного переходу до стандарту, і було вирішено, що було б правильно додати цю переломну зміну, оскільки такий тип коду досить рідкісний? Мені також цікаво, чи будь-які компілятори будуть попереджати у таких випадках ...