什么时候返回值以外的函数使用move vs copy? [英] When does returning a value outside of a function uses move vs copy?

查看:175
本文介绍了什么时候返回值以外的函数使用move vs copy?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

阅读此问题。我创建了这个小小的测试:

After reading this question. I created this small little test:

class A{
public:
    A(){}
    A(const A&){printf("copy\n");}
    A(A&&){printf("move\n");}

    static A f(){
        A a;
        return a;}

    static A g(){
        A a;
        return (a);}//could be return *&a; too.

    static A h(){
        A a;
        return true?a:a;}

 };

结果是(没有RVO和NRVO):

The result is (without RVO and NRVO):


  • f使用移动

  • g使用移动

  • h使用复制

据我所知,用于决定是否使用复制或移动的规则在12.8.32中描述:

As far as I know the rules used to decide whether to use copy or move are described in 12.8.32:


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

  • 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. ...

这是指12.8.31的规则:(我只显示相关部分)

Which refers to the rules of 12.8.31: (I only show the relevant part)


  • 在表达式为非易失性自动对象的名称时,除了函数或catch子句参数)具有与函数返回类型相同的cvunqualified类型,可以通过将自动对象直接构造为函数的返回值来省略复制/移动操作

  • 当没有绑定到引用(12.2)的临时类对象被复制/移动
    到具有相同的cv非限定类型的类对象时,复制/移动操作可以被$ b $省略b b b b b b b b 按照这些规则我明白f和h会发生什么:
  • in a return statement in a function with a class return type, when the expression is the name of a non-volatile automatic object (other than a function or catch-clause parameter) with the same cvunqualified type as the function return type, the copy/move operation can be omitted by constructing the automatic object directly into the function’s return value
  • when a temporary class object that has not been bound to a reference (12.2) would be copied/moved to a class object with the same cv-unqualified type, the copy/move operation can be omitted by constructing the temporary object directly into the target of the omitted copy/move

  • f中的副本适用于elision,因此它被移动。 (参见粗体部分)

  • h中的副本不符合删除条件,因此可以复制。

g?

对我来说,它看起来很像h。我返回一个表达式不是一个自动对象的名称,因此我认为它会被复制,但它被移动。这里发生了什么?

What about g?

推荐答案

在大多数情况下,写入没有区别 a code>(a)。规范的相关部分是§5.1p6(强调我):

解决方案

括号表达式是其类型和值相同的主表达式到那些包含的表达式。括号的存在不影响表达式是否为左值。括号表达式可以与可以使用附加表达式的上下文完全相同,也可以使用相同含义,除非另有说明。

因此,相同的推理适用于您为赋予的 g

A parenthesized expression is a primary expression whose type and value are identical to those of the enclosed expression. The presence of parentheses does not affect whether the expression is an lvalue. The parenthesized expression can be used in exactly the same contexts as those where the enclosed expression can be used, and with the same meaning, except as otherwise indicated.

在上一个标准C ++ 14中,已经澄清了§12.8p32 (强调我):

Hence, the same reasoning applies to the return value of your function g as you have given for f.


当满足复制/移动操作的限制条件但不满足异常声明时,要复制的对象由lvalue指定,或者当return语句中的表达式是(可能带括号的)id-expression时,指定具有在body或parameter-中声明的自动存储持续时间的对象,

In the upcomming standard C++14 this has been clarified §12.8p32 (emphasis mine):

$ b $

对于想知道的人,当括号很重要时,这里是一个例子:


For those who want to know, when the parentheses matter, here is an example:

namespace N {
struct S { };

  void f(S);

}

void g() {
  N::S s;
  f(s); // OK: calls N::f
  (f)(s); // error: N::f not considered; parentheses
          // prevent argument-dependent lookup
}

这篇关于什么时候返回值以外的函数使用move vs copy?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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