乔纳森·韦克利(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,我认为这是一个非常好的主意。

10-06 01:00