C++构造函数、拷贝构造函数、赋值运算符重载 调用时机 GCC与VC在对象作为返回值的不同处理

写一个简单的类来测试构造函数、拷贝构造函数、赋值运算符重载的调用时机。
一个小技巧:cout << this 可以查看当前对象的所在的地址,把它写在某成员函数中,可以检验是哪个对象调用了当前成员函数。
#include <iostream>
using namespace std;




class A {
private:
int data;

public:
A() {
cout << this << " -> constructor " << endl;
}
A(const A& other) {
cout << this << " -> copy constructor " << endl;
}
A& operator=(const A& rhs) {
cout << this << " -> assignment constructor " << endl;
return *this;
}
~A() {
cout << this << " -> destructor " << endl;
}

A operator+(const A& rhs) {
cout << this << " -> overloading add operator " << endl;
this->data += rhs.data;
return *this;
}


};


A addTwo(A a1, A a2) {
cout << "call addTwo() " << endl;
return a1; //拷贝构造函数?
}


A func(A a1) {
cout << "call func() " << endl;
A b1 = a1; //拷贝构造函数
return b1;  //拷贝构造函数?


}


int main() {
A a; //A的构造函数
A b; //B的构造函数
b = addTwo(a, a); //赋值构造函数
b = func(a);

return 0;
}
用GCC编译器对上述源代码进行编译执行,结果如下:
0x22ff28 -> constructor               //main()中的对象a
0x22ff24 -> constructor               //main()中的对象b
0x22ff30 -> copy constructor           //对象a作为参数传递给addTwo()
0x22ff34 -> copy constructor           //对象a作为参数传递给addTwo()
call addTwo()
0x22ff2c -> copy constructor           //addTwo()中 a1+a2 产生一个临时对象作为返回值
0x22ff24 -> assignment constructor    //地址为0x22ff24,与main()中对象b相同,表明这是main()中对象b得到赋值
0x22ff2c -> destructor
0x22ff34 -> destructor
0x22ff30 -> destructor
0x22ff3c -> copy constructor     //对象a作为参数传递给func()
call func()
0x22ff38 -> copy constructor    //func()中,对象b1被赋值为a1  
0x22ff24 -> assignment constructor   //main()中,对象b得到赋值
0x22ff38 -> destructor
0x22ff3c -> destructor
0x22ff24 -> destructor
0x22ff28 -> destructor
结论:普通构造函数的调用时机自不多说;
拷贝构造函数的调用时机有:
1)一个对象以值传递的方式传入函数体; (addTwo()、func()的参数传递)
2)一个对象以值传递的方式从函数体返回;(addTow()返回值,注意func()在返回时没有调用拷贝函数!!!后面解释)
3)一个对象需要通过两外一个对象进行初始化;(func中对象b1需要用a1进行初始化)
赋值运算符重载的调用时机:
在一个对象已经创建之后,对其进行赋值时,就会调用该对象的赋值运算符函数。


在VC编译器上编译和执行同样的源代码,结果如下:
0012FF70 -> constructor            //main()中的对象a
0012FF6C -> constructor             //main()中的对象b
0012FEE4 -> copy constructor         //...
0012FEE0 -> copy constructor         //...
call addTwo()
0012FF60 -> copy constructor         //...
0012FEE0 -> destructor
0012FEE4 -> destructor
0012FF6C -> assignment constructor    //...
0012FF60 -> destructor
0012FEE4 -> copy constructor
call func()
0012FEC8 -> copy constructor         //func()中,对象b1被a1赋值
0012FF58 -> copy constructor         //func()返回时创建临时对象!!! 这在上面的结果中是没有的
0012FEC8 -> destructor
0012FEE4 -> destructor
0012FF6C -> assignment constructor
0012FF58 -> destructor
0012FF6C -> destructor
0012FF70 -> destructor
Press any key to continue
结论:
C/C++ 函数参数和返回值传递机制
指出:GCC 编译器不创建额外的返回值临时对象(即使用-O0参数来关闭优化)
对此,并未给出详细说明,从上述测试代码中可以看出,当被调用函数中创建本地的对象并作为返回值时,就不会再创建临时对象。
我还注意到,如果被调用函数返回的对象正是传递给它的参数之一,这时仍然会创建临时对象。
而VC编译器的表现则和我们常规理解保持一致。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值