简体   繁体   English

返回unique_ptr <Object> as unique_ptr <const Object>

[英]Returning unique_ptr<Object> as unique_ptr<const Object>

I have a method like this: 我有这样的方法:

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

The problem is that it doesn't compile: 问题是它不能编译:

error: cannot bind 'std::unique_ptr' lvalue to 'std::unique_ptr&&' 错误:无法将'std :: unique_ptr'左值绑定到'std :: unique_ptr &&'

I can make it compile by using the following bypass: 我可以使用以下旁路进行编译:

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

But it seems a bit as doing something excessive. 但这似乎有点过分。 I cannot understand, what's wrong with the first piece of code from C++'s point of view? 我无法理解,从C ++的角度看第一段代码有什么问题? Is there more elegant solution? 有更优雅的解决方案吗?

Your code should work fine, because in return statement : 你的代码应该可以正常工作,因为在return语句中

(emphasis mine) (强调我的)

(since C++11) (自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). 如果expression是一个左值表达式并且满足复制精度的条件,或者满足条件,除了表达式命名一个函数参数,那么重载决策选择用于初始化返回值的构造函数执行两次: 首先好像表达式是一个rvalue表达式 (因此它可以选择移动构造函数或引用const的复制构造函数),如果没有合适的转换可用,则第二次执行重载解析,使用左值表达式(因此它可以选择复制构造函数)参考非常数)。

The above rule applies even if the function return type is different from the type of expression (copy elision requires same type) 即使函数返回类型与表达式的类型不同,上述规则也适用(复制省略要求相同类型)

That means, even result is an lvalue, it'll be regarded as an rvalue at first, then the following constructor would be selected, it could convert std::unique_ptr<Stats> to std::unique_ptr<const Stats> . 这意味着,即使result是左值,它首先被视为右值,然后将选择以下构造函数 ,它可以将std::unique_ptr<Stats>转换为std::unique_ptr<const Stats>

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

It seems gcc4.9.2 doesn't behave this way (ie treating the expression as an rvalue expression firstly); 似乎gcc4.9.2没有这种方式(即首先将表达式视为rvalue表达式); gcc 9 just works fine. gcc 9工作得很好。

As @RichardHodges commented , you could use std::move as the workaround . 正如@RichardHodges评论的那样 ,您可以使用std::move作为解决方法

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM