我有这样的方法:
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;
}
问题在于它无法编译:
错误:无法将'std :: unique_ptr'左值绑定到'std :: unique_ptr&amp;&amp;'
我可以使用以下旁路进行编译:
return std::unique_ptr<const Stats>(result.release());
但这似乎有点过分。我无法理解,从C ++的角度看第一段代码有什么问题?有更优雅的解决方案吗?
答案 0 :(得分:4)
您的代码应该可以正常运行,因为在return statement:
(强调我的)
(自C ++ 11起)
如果表达式是左值表达式和复制条件 除了表达式名称a之外,符合或将被满足 函数参数,然后重载决策选择构造函数 用于初始化返回值的执行两次: 首先好像表达式是一个右值表达式(因此它可以选择 移动构造函数或引用const的复制构造函数, 如果没有合适的转换,则重载分辨率为 第二次执行,使用左值表达式(因此可以选择 复制构造函数引用非const)。
即使函数返回类型不同,上述规则也适用 从表达的类型(复制elision需要相同的类型)
这意味着,即使result
是左值,它首先会被视为右值,然后会选择以下constructor,它可以将std::unique_ptr<Stats>
转换为{{ 1}}。
std::unique_ptr<const Stats>
似乎gcc4.9.2没有这样的表现(即首先将表达式视为右值表达式); gcc 9工作正常。
作为@RichardHodges commented,您可以使用template< class U, class E >
unique_ptr( unique_ptr<U, E>&& u ) noexcept;
作为workaround。