目录:
写在前面
1)C++的编译器会默认给一个类提供4个函数
- 默认构造函数(无参、函数体为空)
- 默认析构函数(无参、函数体为空)
- 默认拷贝函数(浅拷贝,对属性仅进行值拷贝)
- 赋值运算符operator=(对属性进行值拷贝)
我们知道类中的默认拷贝构造函数和赋值运算符,都是对属性进行值拷贝,但是它们之间有什么区别吗?在什么情况下会调用它们?下面会详细介绍.
2)本篇涉及内容:
- 拷贝构造函数和赋值运算符的区别
- 如何实现赋值运算符的深拷贝
拷贝构造函数和赋值运算符
从上面代码我们可以知道:
- 默认的拷贝构造函数和赋值运算符重载都是对属性进行简单的值拷贝(浅拷贝),如果属性中有涉及到堆内存的使用需要进行函数重写
那么在什么情况下会调用拷贝构造函数和赋值运算符重载?
-
调用拷贝构造函数的情况:
-
通过一个已存在的对象来构造一个新的对象,此时会调用这个新对象的拷贝构造函数.
-
当一个对象作为函数实参传入时,此时会调用形参的拷贝构造函数.
-
当函数的返回值是一个对象时,此时接受这个函数返回值的对象会调用拷贝构造函数.
从上面的情况我们可以总结出:
当一个已经构造好了的对象去赋值给一个还未构造的对象,此时就会调用这个还未构造的对象的拷贝构造函数,产生的结果是会有新的对象产生.关于深浅拷贝和拷贝构造函数的详细介绍请看:C++的堆与拷贝构造函数
-
-
调用赋值运算符重载的情况:
-
两个对象已经存在,用对象p1去重新赋值给另一个对象p2即
p2 = p1
,此时会调用p2对象的运算符重载.从上述情况我们可以得出:
当一个已经构造好了的对象去重新赋值给另一个构造好了的对象,此时就会调用这个被赋值的对象的运算符重载,这个过程中没有新对象产生.
-
实现赋值运算符重载的深拷贝
下面仔细来看一下实现赋值运算符重载的深拷贝代码
Person& operator= (Person& p) {
//先判断原来的对象是否存在堆区
if (this->m_Age != NULL) {
delete this->m_Age;
this->m_Age = NULL;
}
//深拷贝
this->m_Age = new int(*p.m_Age);
//返回对象本身
return *this;
}
我们可以看见,实现深拷贝的原理和实现拷贝构造函数深拷贝的原理相同,但是这里需要注意的是:
- 进行深拷贝之前要先把原来已经存在的堆内存释放掉
- 返回值是当前对象本身的引用