2

可能重复:
了解返回值优化和返回临时值 - C++

让我们Integer成为某个班级i的成员。left并且right作为参数传递给函数调用并且是类型Integer

现在正如 Bruce Eckel 中给出的那样。

代码 1:

return Integer(left.i+right.i);

代码 2:

Integer tmp(left.i+right.i);
return tmp;

代码 1 说创建一个临时整数对象并返回它,它不同于创建一个命名的局部变量并返回它,这是一个普遍的误解。

在代码 1 中(称为返回临时方法):
编译器知道您对它创建的对象没有其他需要,然后返回它。编译器通过building the object directly into the location of the outside return value. 这只需要一个普通的构造函数调用(没有复制构造函数)并且不需要析构函数,因为没有创建本地对象。

虽然代码 2 中会发生 3 件事:
a) 创建 tmp 对象,包括其构造函数调用
b) the copy-constructor copies the tmp to the location of the outside return value
c) 在作用域结束时为 tmp 调用析构函数。

在代码 1 中这是什么意思:building the object directly into the location of the outside return value
还有为什么在代码 1 中不会调用复制构造函数?

另外我不明白代码2中的步骤b在做什么?即the copy-constructor copies the tmp to the location of the outside return value

4

1 回答 1

2

编译器可以自由优化按值传递和按值返回的复制构造函数。我的猜测是,任何体面的优化器都会为两种变体生成相同的二进制文件。

代码的优化版本:

A foo()
{
   A temp;
00401000  mov         ecx,dword ptr [A::x (40337Ch)] 
00401006  mov         dword ptr [eax],ecx 
00401008  add         ecx,1 
0040100B  mov         dword ptr [A::x (40337Ch)],ecx 
   return temp;
}

所以你看,复制构造函数没有被调用,即使在我的版本中,它有一个cout,所以它确实会影响观察到的行为。

没有优化:

A foo()
{
004113C0  push        ebp  
004113C1  mov         ebp,esp 
004113C3  sub         esp,0CCh 
004113C9  push        ebx  
004113CA  push        esi  
004113CB  push        edi  
004113CC  lea         edi,[ebp-0CCh] 
004113D2  mov         ecx,33h 
004113D7  mov         eax,0CCCCCCCCh 
004113DC  rep stos    dword ptr es:[edi] 
   A temp;
004113DE  lea         ecx,[temp] 
004113E1  call        A::A (4110E6h) 
   return temp;
004113E6  lea         eax,[temp] 
004113E9  push        eax  
004113EA  mov         ecx,dword ptr [ebp+8] 

/// copy constructor called on next line:

004113ED  call        A::A (411177h) 
004113F2  mov         eax,dword ptr [ebp+8] 
}

短语“b) 复制构造函数将 tmp 复制到外部返回值的位置。” 牵强附会,有时甚至不会发生。

你应该记住的是,你不应该依赖被调用的复制构造函数。

于 2012-01-04T08:31:13.007 回答