乔纳森·韦克利(Jonathan Wakely)在comment to another question中回应了我的发言:
->
因此似乎有时我们可能必须在返回时移动局部变量。
这个例子
std::unique_ptr<base> f() {
auto p = std::make_unique<derived>();
p->foo();
return p;
}
很好,因为它给出了compilation error
> prog.cpp:10:14: error: cannot convert ‘p’ from type
> ‘std::unique_ptr<derived>’ to type ‘std::unique_ptr<derived>&&’
但我想知道是否通常有很好的机会可以检测到这一点-这是语言规则或
unique_ptr
的限制吗? 最佳答案
更新:
在现代编译器版本中,不需要显式移动。
核心DR 1579更改了规则,以便即使类型不同,返回值也将被视为右值。 GCC 5为C++ 11和C++ 14实现了新规则。
原答案:
这不是unique_ptr
的限制,它是语言的限制,相同的限制适用于任何调用带有右值引用的转换构造函数的return
语句:
struct U { };
struct T {
T(U&&) { }
};
T f() {
U u;
return u; // error, cannot bind lvalue to U&&
}
由于[class.copy] / 32说:
这意味着
return
语句中的表达式只有在可以进行复制/移动省略符(又称NRVO)的情况下才可以视为右值,但是过于严格,因为它意味着仅当类型完全相同时才使用它,即使该变量始终超出范围,因此始终将其视为rvalue(技术上视为xvalue,即将过期的值)是合理的。这是suggested(以前是Xeo)最近的Richard Smith,我认为这是一个非常好的主意。