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

Returning unique_ptr<Object> as unique_ptr<const Object>

我有这样的方法:

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;
}

问题是它没有编译:

error: cannot bind ‘std::unique_ptr’ lvalue to ‘std::unique_ptr&&’

我可以使用以下绕过方法使其编译:

return std::unique_ptr<const Stats>(result.release());

不过好像有点过分了。我无法理解,从 C++ 的角度来看,第一段代码有什么问题?有没有更优雅的解决方案?

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

(强调我的)

(since C++11)

If expression is an lvalue expression and the conditions for copy elision are met, or would be met, except that expression names a function parameter, then overload resolution to select the constructor to use for initialization of the returned value is performed twice: first as if expression were an rvalue expression (thus it may select the move constructor or a copy constructor taking reference to const), and if no suitable conversion is available, overload resolution is performed the second time, with lvalue expression (so it may select the copy constructor taking a reference to non-const).

The above rule applies even if the function return type is different from the type of expression (copy elision requires same type)

也就是说,即使result是左值,也会先把它当成右值,然后后面的constructor会被选中,可以把std::unique_ptr<Stats>转换成std::unique_ptr<const Stats>.

template< class U, class E >
unique_ptr( unique_ptr<U, E>&& u ) noexcept;

gcc4.9.2 似乎不是这样的(即首先将表达式视为右值表达式); gcc 9 工作正常。

, you could use std::move as the workaround.