组合类构造函数、析构函数、拷贝构造函数的调用顺序

组合类构造函数、析构函数、拷贝构造函数的调用顺序

这些天在看C++的过程中一直搞不太懂构造函数和析构函数的调用顺序,特别是析构函数,不带参数不好进行测试,这里把这几天遇到的问题写了个代码跑了一下,和大家分享一下,写的有不对的地方,欢迎大家批评指正。

测试代码

#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>

using namespace std;

class Point{
    
    
private:
	int m_x;
	int m_y;
public:
	Point(int x, int y) : m_x(x), m_y(y){
    
    
		cout << "Point的初始化列表构造函数调用" << m_x << " " << m_y << endl;
	}
	~Point(){
    
    
		cout << "Point的析构函数调用" << m_x << " " << m_y << endl;
	}
	Point(Point &P){
    
    
		m_x = P.m_x; m_y = P.m_y;
		cout << "Point的拷贝构造函数调用" << m_x << " " << m_y << endl;
	}
	int getX(){
    
    
		return m_x;
	}
	int getY(){
    
    
		return m_y;
	}
};

class Line{
    
    
private:
	Point m_s, m_e;
public:
	Line(Point s, Point e) : m_s(s), m_e(e){
    
    
		cout << "Line的初始化列表构造函数调用" << endl;
	}
	Line(Line &L) : m_s(L.m_s), m_e(L.m_e){
    
    
		cout << "Line的拷贝构造函数调用" << endl;
	}
	~Line(){
    
    
		cout << "Line的析构函数调用" << endl;
	}
	double getDis(){
    
    
		double x = double(m_s.getX() - m_e.getX());
		double y = double(m_s.getY() - m_e.getY());
		return sqrt(x * x - y * y);
	}
};

int main(){
    
    
	Point p1(1, 2), p2(3, 4);
	cout << "---------------------" << endl;
	Line L1(p1, p2);
	cout << "---------------------" << endl;
	Line L2(L1);
	return 0;
}

运行结果

在这里插入图片描述

下面逐一对输出结果进行解释

Point的初始化列表构造函数调用1 2
Point的初始化列表构造函数调用3 4

上面两句的输出很好理解,对应的是源码的第52行,即创建Point类的对象p1、p2时,调用了Point类的初始化列表构造函数,于是输出了上述结果。

---------------------
Point的拷贝构造函数调用3 4
Point的拷贝构造函数调用1 2

上面的这两句是创建组合类Line的对象L1的时候,首先需要形参传递给实参,这个过程会调用Point类的拷贝构造函数【当对象作为函数参数或者返回值的时候会调用拷贝构造函数】,注意此时参数的传递顺序是从右到左,所以这里会调用Point的拷贝构造函数两次,又因为从右到左,所以先拷贝e,后拷贝s。

Point的拷贝构造函数调用1 2
Point的拷贝构造函数调用3 4

这里的两句是调用Point的拷贝构造函数,分别完成内嵌对象m_s、m_e的初始化,即执行的是Line构造函数中的这个部分[m_s(s), m_e(e)]。

Line的初始化列表构造函数调用

上面的这句就是执行Line构造函数的函数体输出的结果。

Point的析构函数调用1 2
Point的析构函数调用3 4

这里是对形参的析构,上面说到了先拷贝的e,后拷贝的s,所以释放的时候,先释放s所占内存,后释放e所占内存。【系统在栈中为对象分配内存空间,而栈是采用后进先出的工作方式

---------------------
Point的拷贝构造函数调用1 2
Point的拷贝构造函数调用3 4

这上面的两句执行的是Line的拷贝构造函数,具体对应的是Line拷贝构造函数中的这个部分[ m_s(L.m_s), m_e(L.m_e) ]。

Line的拷贝构造函数调用

执行Line拷贝构造函数的函数体时输出的结果

Line的析构函数调用
Point的析构函数调用3 4
Point的析构函数调用1 2

以上的三句需要一起解释,在对Line的拷贝构造函数之中,我们使用的是L1来实例化L2,这个过程中需要注意,三个对象的定义顺序为L2.m_s、L2.m_e、L2,所以对应的析构顺序为L2、L2.m_e、L2.m_s。

Line的析构函数调用
Point的析构函数调用3 4
Point的析构函数调用1 2

同理。这里的三句输出和上面的一样,三个对象的定义顺序为m_s、m_y、L1,所以对应的析构顺序为L1、m_y、m_x。

Point的析构函数调用3 4
Point的析构函数调用1 2

上面两句是对p1、p2的析构,与定义它们的顺序相反。

猜你喜欢

转载自blog.csdn.net/shangzhengyu/article/details/113827867
今日推荐