《C++语言程序设计基础》学习之对象复制与移动

浅层复制与深层复制
浅层复制,实现对象间数据元素的一一对应复制。
深层复制,当被复制的对象数据成员是指针类型时,不是复制该指针成员本身,而是将指针所指对象进行复制。
对象的浅层复制:传递的是指针的值

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),双个的引用&&可以绑定到右值

猜你喜欢

转载自blog.csdn.net/shiheyingzhe/article/details/82939927