什么时候需要返回语句的显式移动? [英] When is explicit move needed for a return statement?

查看:158
本文介绍了什么时候需要返回语句的显式移动?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对另一个问题的评论 Jonathan Wakely回复了我的声明:


你不需要显式移动局部变量函数return
value。这是隐含的移动。


- >


... never never never ...如果局部变量
与返回类型不是相同的类型,则需要显式移动,例如 std :: unique_ptr< base>
f(){auto p = std :: make_unique< derived>(); p-> foo(); return p; }
,但
如果类型是相同的,它将移动,如果可能...


因此,有时我们可能需要在返回时移动一个局部变量。



示例

  std :: unique_ptr< base> f(){
auto p = std :: make_unique< derived>();
p-> foo();
return p;
}

很好,因为它给出了编译错误

 > prog.cpp:10:14:错误:无法从类型
转换'p'> 'std :: unique_ptr< deriv>'to type'std :: unique_ptr< derived>&&'

但我想知道是否有很好的机会来检测这一般 - 和这里是语言规则的限制或 unique_ptr

解决方案

这不是 unique_ptr ,这是语言的限制,同样的限制适用于任何 return 语句,它调用转换构造函数获取右值引用:

  struct U {}; 

struct T {
T(U&&){}
};

T f(){
U u;
return u; //错误,无法将lvalue绑定到U&&
}

这不会编译,因为[class.copy] / 32说: p>


当满足复制操作的删除标准时,除非源对象是函数参数,否则满足或满足,要复制的对象由一个左值指定,重载分辨率选择该复制的构造函数首先被执行,就好像对象是由右值指定的一样。


这意味着 return 语句中的表达式只有在适用于复制/移动精确(也称为NRVO)时才能被视为右值,但是过于限制,因为它意味着它只适用于类型是完全相同的,即使变量总是超出范围,所以总是认为是一个右值(技术上作为xvalue,一个 / em>值。)



这是最近的 Richard Smith 提供的-proposals / Tc1p52jg-1Y / aTEsPprxzZgJ =nofollow>建议

更新:
核心 DR 1579 更改了规则,以便返回值将被视为右值即使类型不一样。 GCC 5实现了新规则,用于C ++ 11以及C ++ 14。


In a comment to another question Jonathan Wakely responds to my statement:

You never need explicit move for a local variable function return value. It's implicit move there

->

... never say never ... You need an explicit move if the local variable is not the same type as the return type, e.g. std::unique_ptr<base> f() { auto p = std::make_unique<derived>(); p->foo(); return p; }, but if the types are the same it will move if possible ...

So it seems sometimes we may have to move a local variable on return.

The example

std::unique_ptr<base> f() { 
  auto p = std::make_unique<derived>();
  p->foo(); 
  return p; 
}

is nice in that it gives a compilation error

> prog.cpp:10:14: error: cannot convert ‘p’ from type
> ‘std::unique_ptr<derived>’ to type ‘std::unique_ptr<derived>&&’

but I'm wondering whether there is a good chance to detect this in general -- and is this here a limit of the language rules or of unique_ptr??

解决方案

This is not a limitation of unique_ptr, it's a limitation of the language, the same limitation applies to any return statement that calls a converting constructor taking an rvalue reference:

struct U { };

struct T {
  T(U&&) { }
};

T f() {
  U u;
  return u;  // error, cannot bind lvalue to U&&
}

This will not compile because [class.copy]/32 says:

When the criteria for elision of a copy operation are met or would be met save for the fact that the source object is a function parameter, and the object to be copied is designated by an lvalue, overload resolution to select the constructor for the copy is first performed as if the object were designated by an rvalue.

This means that the expression in a return statement can only be treated as an rvalue if it is eligible for copy/move elision (aka NRVO) but that is too restrictive because it means it only applies when the type is exactly the same, even though the variable is always going out of scope so it would be reasonable to always treat is as an rvalue (technically as an xvalue, an expiring value.)

This was recently suggested by Richard Smith (and previously by Xeo) and I think it's a very good idea.

Update: Core DR 1579 changed the rules so that the return value will be treated as an rvalue even when the types are not the same. GCC 5 implements the new rule, for C++11 as well as C++14.

这篇关于什么时候需要返回语句的显式移动?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆