我的理解是,在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
如果查看输出,则有所不同。
因此,我想这个问题现在变成了,在向标准中添加隐式移动时是否考虑了这个问题,并且决定可以添加此重大更改,因为这种代码非常稀有吗?我也想知道在这种情况下是否有任何编译器会发出警告...