Насколько я понимаю, в 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
Если вы посмотрите на вывод, он другой.
Итак, я полагаю, что теперь возникает вопрос, учитывался ли этот вопрос при добавлении неявного перемещения в стандарт, и было решено, что можно было бы добавить это критическое изменение, так как этот вид кода достаточно редок? Мне также интересно, предупредит ли какой-либо компилятор в таких случаях ...