operator+的规范实现涉及到额外的移动构造函数。

问题描述 投票:2回答:1

动机是 这个问题我比较了二进制的两个不同版本的实现。operator+ 就...而言 operator+=. 考虑我们在类的定义里面 X.

第一版

friend X operator+(X lhs, const X& rhs)   
{
   lhs += rhs;  
   return lhs; 
}

第二版

friend X operator+(const X& lhs, const X& rhs) 
{    
   X temp(lhs);
   temp += rhs;
   return temp;
}

friend X operator+(X&& lhs, const X& rhs) 
{    
   lhs += rhs;
   return std::move(lhs);
}

其中,在这两种情况下。operator+= 定义如下。

X& operator+=(const X& rhs)    
{                             
  ... // whatever to add contents of X
  return *this;   
}

现在,我只是运行下面的代码,并跟踪copymove构造函数的调用。

X a, b, c;
X d = a + b + c;

第一个 "规范" 版本,有1个副本+ 2动 构造函数的调用,而第二个版本只有1个拷贝+的 1招 构造函数调用(用GCC 10和 -O3).

问题是:在第一种情况下,是什么阻碍了那个额外的移动构造函数调用的洗脱?在第一种情况下,是什么阻碍了额外的移动构造函数调用的省略?

现场演示。https:/godbolt.orgzGWEnHJ。


补充意见: 在现场演示中,当类中有一些内容(整数成员变量)时,移动构造函数会调用 不属于 衬托 前二分之一 版本。分别. 另外,在第二个版本中,最终结果6在编译时计算,并硬编码到汇编中(当传递给 operator<<),而第一个版本则是从内存中读取。一般来说,第二个版本似乎(相对)更有效率。 但这很可能是由那些 cout 所涉及的消息。如果没有它们,汇编的输出是完全一样的。

c++ operator-overloading pass-by-reference pass-by-value
1个回答
2
投票

在第一种情况下,是什么阻碍了那个额外的移动构造函数调用的精简?

缺陷报告 DR1148 被接受并包含在C++11中。

简而言之,它说(强调我):

不清楚在返回类型参数时,是否允许复制删除。如果不允许,仍然可以移动而不是复制返回值。

建议的解决方案。修正第34段 明确地将函数参数排除在复制洗脱之外。. 修正第35段,将功能参数列为符合移动施工条件的参数。

结果见:[class.copy.elision]1.1。 (强调我)

在...中 return 类返回类型的函数中的语句,当 表情 是一个具有自动存储时间的非易失性对象的名称(非函数参数 或一个变量引入的 异常声明处理者 ([except.handle])),类型与函数返回类型相同(忽略cv限定),可以直接将对象构造到函数调用的返回对象中,省略copymove操作

© www.soinside.com 2019 - 2024. All rights reserved.