G++的结果为:
而VC6的结果为:
第158行:VECTOR3 v1 = Func1();
像普通的函数如: 然后,编译器会把158拆成两行:
所以,对于第158行,只输出一行带参constructor的log。
第162行:v1 = Func1();
该语句的执行过程本该是:
1>. 在 Func1() 中构造一个无名对象
2>. 由 Func1() 中的无名对象拷贝构造调用表达式处的临时对象
3>. 再由临时对象赋值给v1 (赋值运算符)
4>. Func1() 返回,析构无名对象
5>. 整个语句结束,析构临时对象
但是这时候无名对象并没有创建,一个临时对象创建,并直接调用临时对象的parameters constructor。这和第158行有些类似。编译器所产生的代码为:
第166行:VECTOR3 v2 = Func2();
先解释VC6的结果,类似第158行,编译器产生了如下的码:
而为什么G++只产生了一行对default constructor的调用,是因为G++可能做了NRV优化。产生NRV优化的目的是:为了压抑上面的第17行对copy constructor的调用,因为bitewise的效率要比copy constructor要高。当bitewise足够用时,我们没有必有进行NRV优化。如果客户显式增加了copy constructor,其拷贝的开销将会增大。为了避免不必要的copy constructor调用,于是需要进行NRV优化。经过NRV产生的码为:
所以,只输出了一行default constructor的调用。
第170行不解释.
第174行:v3 = Func2();
首先被转换成两行,有一个临时对象,这对于所有编译器都是一样的: 其中的第一行产生跟166行一样的代码,对于VC6来说是3行,对于做过NRV优化的G++来说只有一行。然后接下来的过程相同:产生对operator=的调用,右边为临时对象temp_1,左边为v3;然后产生对destructor的调用析构掉temp_1。最后一次性析构掉v1,v2,v3。
PS:
而参数的初始化有两种方式:另一种是直接拷贝构建,书上未作详细解释。