C++基础:类的构造、析构、拷贝构造、赋值重载函数
作者:
jokerlove
,
2022-09-11 21:18:04
,
所有人可见
,
阅读 182
/*
什么时候调用赋值重载什么时候调用拷贝构造?
A a2 = a1; 创建值为a1的对象a2,此时属于构造对象阶段,因此是拷贝构造,等同A a2(a1);
A a3; a3 = a1; 此时已经有对象a3了,所以调用的是对象a3的operator=(a1);
不是有=就赋值重载
以下赋值语句区别?没有区别
A a4;
a4 = A(30);
a4 = (A)30;
a4 = 30;
都是对已存在对象a4的赋值操作,因为赋值重载传引用,需要初始化对象,所以都会构造临时对象再析构
第一个常规赋值重载,前两个显式生成对象,第三个隐式生成对象,转换都需要看类中是否有合适的构造函数
对于这个类,如果a4 = "abc";就肯定不行
*/
class A {
private:
int data;
public:
A(int val = 0) :data(val) {
cout << "A构造函数" << endl;
}
~A() {
cout << "~A析构函数" << endl;
}
A(const A& tmp) :data(tmp.data) {
cout << "A的拷贝构造函数" << endl;
}
A& operator=(const A& tmp) {
cout << "A的赋值重载函数" << endl;
data = tmp.data;
return *this;
}
};
int main()
{
A a1; // 构造
A a2(a1); // 拷贝构造
A a3 = a1; // 拷贝构造 注意区分赋值重载和拷贝构造时机
A a4 = A(20); // 构造 临时对象A(20)的拷贝析构被编译器优化掉了
A a5(20); // 构造 等同a4写法,都是传入临时值进行构造
cout << "=========================================================================" << endl;
a5 = a1; // 赋值重载 不涉及构造新对象,所以是赋值重载
a5 = A(30); // 构造+赋值重载+析构 赋值重载需要引用一个初始化对象去赋值,所以A(30)也需要构造
// 先构造A(30),再赋值重载=,再析构A(30)
a5 = (A)30; // 构造+赋值重载+析构 int显式转换A,需要看是否有对应类型(int)的构造函数
// 有就隐式转换生成临时对象,语句结束后析构
a5 = 30; // 构造+赋值重载+析构 int隐式转换A,同理
cout << "=========================================================================" << endl;
static A a6 = A(40); // 注意static在编译期开辟内存,但运行到这里时才进行初始化
cout << "=========================================================================" << endl;
//A* p1 = &A(50); // 编译器报错,语句结束A(50)析构,所以不要用指针指向临时对象
A* p2 = new A(50); // 是在堆上new对象,不是临时对象,所以不会立马析构
A* p3 = new A[2]; // new了一个对象数组,所以要构造两次
const A& p4 = A(50); // 引用就是别名,所以A(50)的生命周期等同于p3,而不是语句结束析构
cout << "=========================================================================" << endl;
delete p2;
delete[]p3; // 因为是new了对象,所以一定要记得delete
return 0;
}