何时左值移动而不是在C ++中复制? [英] When are lvalues moved instead of copied in C++?

查看:67
本文介绍了何时左值移动而不是在C ++中复制?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

给出以下内容:

Foo getFoo()
{
    Foo result = doSomeWork();
    return result;
}

  • C ++是否保证将移动result,而不是复制?或者换句话说,编写return std::move(result)是多余的吗?

    • Does C++ guarantee that result will be moved, instead of copied? Or to put it another way, is writing return std::move(result) superfluous?

      在没有明确的std::move强制转换的情况下,是否有其他标准规定标准将左值静默移动而不是复制?

      Are there any (other) situations where the standard specifies that a lvalue will be silently moved instead of copied, in the absence of an explicit std::move cast?

      注释:

      • 假设Foo是可移动构造的.

      忽略复制/移动省略号,这可能另外适用.

      Disregarding copy/move elision, which may apply in addition.

      推荐答案

      1. 尽管可能会忽略这一举动,是的.如果移动构造函数可用,则复制永远不会发生.为了清楚起见,我将再次引用该段. [class.copy]/32:

      1. Despite the fact that the move might be elided, Yes. A copy will never happen if a move constructor is available. I'll quote the paragraph again for clarity. [class.copy]/32:

      满足复制/移动操作的省略标准,但是 不是 exception-declaration (例外声明),,并且要复制的对象是 由左值指定,或者当return中的表达式指定时 语句是一个(可能带有括号的) id-expression ,它命名为 在主体中声明了具有自动存储期限的对象,或者 最内层的封闭函数或 lambda-expression parameter-declaration-clause 首先选择要为副本选择构造函数的重载分辨率该对象由一个 右值.如果第一个过载解析失败或没有失败 执行,或者所选第一个参数的类型 构造函数不是对对象类型的右值引用(可能是 cv合格),考虑到 对象作为左值. [注意:此两阶段重载解决方案必须 不管是否会出现复制省略都可以执行.它 确定在不执行省略的情况下要调用的构造函数, 并且即使调用为 消失了. —尾注]

      When the criteria for elision of a copy/move operation are met, but not for an exception-declaration, and the object to be copied is designated by an lvalue, or when the expression in a return statement is a (possibly parenthesized) id-expression that names an object with automatic storage duration declared in the body or parameter-declaration-clause of the innermost enclosing function or lambda-expression, overload resolution to select the constructor for the copy is first performed as if the object were designated by an rvalue. If the first overload resolution fails or was not performed, or if the type of the first parameter of the selected constructor is not an rvalue reference to the object’s type (possibly cv-qualified), overload resolution is performed again, considering the object as an lvalue. [Note: This two-stage overload resolution must be performed regardless of whether copy elision will occur. It determines the constructor to be called if elision is not performed, and the selected constructor must be accessible even if the call is elided. — end note ]

      应用std::move并不是多余的,但实际上防止执行复制省略,[class.copy]/31:

      Applying std::move is not superfluous but actually prevents copy elision from being performed, [class.copy]/31:

      -在具有类返回类型的函数中的return语句中,当 表达式为非易失性自动对象的名称 [..]

      — in a return statement in a function with a class return type, when the expression is the name of a non-volatile automatic object [..]

    • 是的,在一种情况下-我再次假设您的意思是,如果不执行复制省略,则将执行一次移动(如果左值被移动,复制省略必须适用).
      考虑一下:

    • Yes, one situation - Again I assume you meant that if copy elision isn't performed, a move is done (Copy elision must be applicable if the lvalue is moved, s.a.).
      Consider this:

      A a;
      throw a;
      

      符合条件:

      -在 throw-expression 中,当操作数是a的名称时 非易失性自动对象(功能或子句除外) 参数),其范围不会超出最里面的末尾 包含try-block(如果有),则从 可以通过以下方式省略对异常对象(15.1)的操作数: 直接将自动对象构造为异常对象

      — in a throw-expression, when the operand is the name of a non-volatile automatic object (other than a function or catch-clause parameter) whose scope does not extend beyond the end of the innermost enclosing try-block (if there is one), the copy/move operation from the operand to the exception object (15.1) can be omitted by constructing the automatic object directly into the exception object

      演示 .
      这是唯一的一个左值被移动而不是被复制的情况.复制省略的其他两种情况仅包括未绑定到引用的临时变量(因此必须由prvalues指定)和例外声明thingy,此处无趣,因为它涵盖了我们未看到的例外对象.

      Demo.
      This is the only other case where an lvalue is moved instead of copied; The other two cases for copy elision solely include temporaries not bound to a reference (which must therefore be designated by prvalues) and the exception-declaration thingy, which is uninteresting here as it covers the exception object we don't see.

      这篇关于何时左值移动而不是在C ++中复制?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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