浅层复制与深层复制
浅层复制,实现对象间数据元素的一一对应复制。
深层复制,当被复制的对象数据成员是指针类型时,不是复制该指针成员本身,而是将指针所指对象进行复制。
对象的浅层复制:传递的是指针的值
class Point {
public:
Point() :x(0), y(0) { cout << "Default Constructor called." << endl; }
Point(int x, int y) :x(x), y(y) { cout << "Constructor called." << endl; }
~Point() { cout << "Destructor called." << endl; }
int getX()const { return x; }//常函数成员处理常对象
int getY()const { return y; }
void move(int newX, int newY) {
x = newX;
y = newY;
}
private:
int x, y;
};
class ArrayOfPoints { //动态数组类
public:
ArrayOfPoints(int size) :size(size) { points = new Point[size]; }
~ArrayOfPoints() {
cout << "Deleting..." << endl;
}
Point& element(int index) { //返回数组元素的引用
assert(index >= 0 && index < size);
return points[index];
}
private:
Point *points;//指向动态数组首地址
int size; //数组大小
};
int main() {
int count;
cout << "Please enter the count of points:";
cin >> count;
ArrayOfPoints points(count);//创建数组对象
//points.element(0)调用类函数,返回对象数组中的元素的引用,访问数组元素的成员
points.element(0).move(5, 0);
points.element(1).move(15, 20);//访问数组元素的成员
ArrayOfPoints pointsArrayt(points);//创建副本指针指向原先的数组
cout << "Copy of points:" << endl;
cout << "Point_0 of array2: " << pointsArrayt.element(0).getX() << ", "
<< pointsArrayt.element(0).getY() << endl;
cout << "Point_1 of array2: " << pointsArrayt.element(1).getX() << ", "
<< pointsArrayt.element(1).getY() << endl;
points.element(0).move(25, 30);
points.element(1).move(35, 40);
cout << "After the moving of points:" << endl;
cout << "Point_0 of array2: " << pointsArrayt.element(0).getX() << ", "
<< pointsArrayt.element(0).getY() << endl;
cout << "Point_1 of array2: " << pointsArrayt.element(1).getX() << ", "
<< pointsArrayt.element(1).getY() << endl;
return 0;
}
对象的深层复制:
在类ArrayOfPoints中增加复制构造函数
class Point {
public:
Point() :x(0), y(0) { cout << "Default Constructor called." << endl; }
Point(int x, int y) :x(x), y(y) { cout << "Constructor called." << endl; }
~Point() { cout << "Destructor called." << endl; }
int getX()const { return x; }//常函数成员处理常对象
int getY()const { return y; }
void move(int newX, int newY) {
x = newX;
y = newY;
}
private:
int x, y;
};
class ArrayOfPoints { //动态数组类
public:
ArrayOfPoints(int size) :size(size) { points = new Point[size]; }
~ArrayOfPoints() {
cout << "Deleting..." << endl;
}
Point& element(int index) { //返回数组元素的引用
assert(index >= 0 && index < size);
return points[index];
}
ArrayOfPoints(const ArrayOfPoints& pointsArray);
private:
Point *points;//指向动态数组首地址
int size; //数组大小
};
ArrayOfPoints::ArrayOfPoints(const ArrayOfPoints& v) { //复制构造函数
cout << "Copy function done!";
size = v.size;
points = new Point[size];
for (int i = 0; i < size; i++)
points[i] = v.points[i];
}
int main() {
int count;
cout << "Please enter the count of points:";
cin >> count;
ArrayOfPoints points(count);//创建数组对象
//points.element(0)调用类函数,返回对象数组中的元素的引用,访问数组元素的成员
points.element(0).move(5, 0);
points.element(1).move(15, 20);//访问数组元素的成员
ArrayOfPoints pointsArrayt(points);//创建副本指针指向原先的数组
cout << "Copy of points:" << endl;
cout << "Point_0 of array2: " << pointsArrayt.element(0).getX() << ", "
<< pointsArrayt.element(0).getY() << endl;
cout << "Point_1 of array2: " << pointsArrayt.element(1).getX() << ", "
<< pointsArrayt.element(1).getY() << endl;
points.element(0).move(25, 30);
points.element(1).move(35, 40);
cout << "After the moving of points:" << endl;
cout << "Point_0 of array2: " << pointsArrayt.element(0).getX() << ", "
<< pointsArrayt.element(0).getY() << endl;
cout << "Point_1 of array2: " << pointsArrayt.element(1).getX() << ", "
<< pointsArrayt.element(1).getY() << endl;
return 0;
}
C++11标准中提供了一种新的构造方法——移动构造。
C++11之前,如果要将源对象的状态转移到目标对象只能通过复制。
在某些情况下,我们没有必要复制对象——只需要移动它们。
C++11引入移动语义:源对象资源的控制权全部交给目标对象
使用复制构造:
class IntNum {
public:
IntNum(int x = 0) :xptr(new int(x)) { //构造函数
cout << "Calling constructor..." << endl;
}
IntNum(const IntNum &n):xptr(new int(*n.xptr)){//复制构造函数
cout << "Calling copy constructor..." << endl;
}
~IntNum(){ //析构函数
delete xptr;
cout << "Destructing..." << endl;
}
int getInt() { return *xptr; }
private:
int *xptr;
};
//返回值为IntNum类临时对象
IntNum getNum() {
IntNum a; //声明并创建对象a
return a; //由于是局部变量会消亡,返回临时变量,会调用复制构造函数
}
int main(){
cout << getNum().getInt() << endl;
return 0;
}
使用移动构造函数:将要返回的局部对象即将要消亡的对象转移到主调函数,省去了构造和删除临时对象的过程。
class IntNum {
public:
IntNum(int x = 0) :xptr(new int(x)) { //构造函数
cout << "Calling constructor..." << endl;
}
IntNum(const IntNum &n) :xptr(new int(*n.xptr)) {//复制构造函数
cout << "Calling copy constructor..." << endl;
}
IntNum(IntNum &&n) :xptr(n.xptr) {//移动构造函数
n.xptr = nullptr;//将n.xptr的指针设置为空指针,指向对象的新的指针是xptr
cout << "Calling move constructor..." << endl;
}
~IntNum() { //析构函数
delete xptr;
cout << "Destructing..." << endl;
}
int getInt() { return *xptr; }
private:
int *xptr;
};
//返回值为IntNum类临时对象
IntNum getNum() {
IntNum a; //声明并创建对象a
return a; //由于是局部变量会消亡,返回临时变量,会调用复制构造函数
}
int main() {
cout << getNum().getInt() << endl;
return 0;
}
IntNum(IntNum &&n) //移动构造函数中的&&是右值引用:即将消亡的值就是右值;函数返回的临时变量也是右值
单个的引用可以绑定到左值:IntNum(const IntNum &n),双个的引用&&可以绑定到右值