将unique_ptr <Object>作为unique_ptr <const Object>返回

Ale*_*xey 5 c++ const return unique-ptr c++11

我有这样的方法:

std::unique_ptr<const Stats> Table::GetStats() const {
  std::unique_ptr<Stats> result;
  // ...
  // Prepare stats. Under some conditions an exception may be thrown.
  // ...
  return result;
}
Run Code Online (Sandbox Code Playgroud)

问题是它不能编译:

错误:无法将'std :: unique_ptr'左值绑定到'std :: unique_ptr &&'

我可以使用以下旁路进行编译:

return std::unique_ptr<const Stats>(result.release());
Run Code Online (Sandbox Code Playgroud)

但这似乎有点过分.我无法理解,从C++的角度看第一段代码有什么问题?有更优雅的解决方案吗?

son*_*yao 4

您的代码应该可以正常工作,因为在return 语句中:

(强调我的)

(自 C++11 起)

如果表达式是左值表达式,并且满足或将满足复制省略的条件(表达式命名为函数参数除外),则执行重载解析以选择用于初始化返回值的构造函数两次:第一次是 if表达式是一个右值表达式(因此它可以选择移动构造函数或引用 const 的复制构造函数),如果没有合适的转换可用,则使用左值表达式第二次执行重载解析(因此它可以选择复制构造函数引用非常量)。

即使函数返回类型与表达式类型不同,上述规则也适用(复制省略需要相同类型)

这意味着,即使result是左值,它也会首先被视为右值,然后选择以下构造函数std::unique_ptr<Stats>,它可以转换为std::unique_ptr<const Stats>.

template< class U, class E >
unique_ptr( unique_ptr<U, E>&& u ) noexcept;
Run Code Online (Sandbox Code Playgroud)

看来 gcc4.9.2 没有这样的行为(即首先将表达式视为右值表达式);海湾合作委员会9工作正常。

正如@RichardHodges 评论的那样,您可以使用std::move作为解决方法