复制与赋值
- 复制: 将数据从源对象传输到目标对象,使得两个对象的数据相同。单独的复制通常是初始化操作,即复制初始化。
- 赋值:擦除左操作数中的当前值,然后存入右操作数的值。
复制=擦除+复制,对于基本类型的变量来说,出于优化的目的,赋值通常可以省去擦除操作,因此与复制没有多大的差别,但是我们将看到,对于类对象来说,二者有非常大的差别。 - 在定义类时,可以通过自定义的复制构造函数,/operator=重载函数来显示地控制类对象复制/赋值操作的行为,否则系统会隐式地生成一个复制构造函数/赋值操作符重载函数。
Grade g1 = g2;//复制初始化,调用隐式复制构造函数完成
g1 = g3;//赋值,调用隐式operator =重载函数完成
**复制操作:**下面5种情况:
- 用花括号列表初始化一个数组的元素:int a[ ] = {0,1,2,3,4,5};
- 函数参数的值传递 vectorvi;double d = media9(vi);
- 使用复制初始化定义对象:string s2 = s1;string s3{s1};int i{10};
- 函数通过返回语句复制一个非引用类型的值到临时对象中
- 构造函数的成员初始中。
隐式复制构造函数:
隐式复制构造函数的默认行为是实现对象之间数据成员的逐成员复制,这种对象的复制成为浅复制。
对于具有资源的类来说,隐式复制构造函数提供的浅复制并不能满足对象完整复制的要求,此事实为其自定义复制构造函数。
A::A(const A &o):m1{o.m1},m2{o.m2},...,mn{o.mn} {}
隐式生成的函数只能实现浅复制
owner指针:在部分对象比较大或者死亡期不相同时,通常组合关系实现为组合对象中拥有部分对象的指针,即具有所有权语义的owner指针。
具有owner指针的组合对象在复制/赋值时,必须进行深复制/深赋值,在销毁时,必须销毁owner指针指向的———作为资源的——部分对象。
//owner 指针
Class Plane
{
public:
Plane(PlaneCategory category,std::string modelNumber);
private:
PlaneCategory m_category;
std::string m_modelNumber;
Cockpit *_cockpit;
};
Class Cockpit
{
public:
Cockpit(PlaneCategory category,std::string modelNumber);
void refuel();
private:
int m_range;
};