C++Note 构造析构函数调用规则 深浅拷贝
默认情况下,C++编译器至少给一个类添加3个函数
*1.默认构造函数(无参,函数体为空)
*2.默认析构函数(无参,函数体为空)
*3.默认拷贝构造函数,对属性进行值拷贝
构造函数调用规则如下:
*如果用户定义有参构造函数,C++不再提供默认无参构造,但是会提供默认拷贝构造
*如果用户定义拷贝构造函数,C++不会再提供其他普通构造函数
浅拷贝:简单的赋值拷贝操作(编译器提供)
问题:拷贝构造函数使用时,构造函数变量有地址传递,当析构函数释放操作时,堆区的内存 重复释放 产生问题
当构造函数需要开辟堆区的数据,此时使用拷贝构造会指向同一块内存,产生堆区内存的重复释放
1 Person(const Person &p) 2 { 3 cout << "Person拷贝构造函数的调用" << endl; 4 m_Age = p.m_Age;//浅拷贝:编译器默认写 5 m_Height = p.m_Height;//编译器默认写 6 }
1 class Person 2 { 3 public: 4 Person() 5 { 6 cout << "Person默认构造函数的调用" << endl; 7 } 8 Person(int age,int height) 9 { 10 m_Age = age; 11 m_Height = new int(height); 12 } 13 Person(const Person &p) 14 { 15 cout << "Person拷贝构造函数的调用" << endl; 16 } 17 ~Person() 18 { 19 //析构代码 在堆区开辟数据释放操作 20 if (m_Height != NULL)//如果身高内存不为空 则需释放 21 { 22 delete m_Height;//释放内存 23 m_Height = NULL;//防止野指针出现 24 } 25 cout << "Person析构函数的调用"<< endl; 26 } 27 int m_Age;//年龄 28 int* m_Height;//身高 地址 堆区开辟空间 拷贝构造会指向同一块内存 29 };
浅拷贝的问题要利用深拷贝来解决
深拷贝:在堆区重新申请空间,进行拷贝操作
1 Person(const Person &p) 2 { 3 cout << "Person拷贝构造函数的调用" << endl; 4 m_Age = p.m_Age;//m_Age为变量 值传递 正常 5 //m_Height = p.m_Height;//编译器默认实现这行代码 浅拷贝 错误 6 //深拷贝操作(涉及地址传递的时候使用) 7 m_Height = new int(*p.m_Height); 8 }
析构:
如果堆区有内存(地址类型:如上 m_Height)则需要在析构代码中将堆区内存释放干净(代码规范)
1 ~Person() 2 { 3 //析构代码 在堆区开辟数据释放操作 4 if (m_Height != NULL)//如果身高内存不为空 则需释放 5 { 6 delete m_Height;//释放内存 7 m_Height = NULL;//防止野指针出现 8 } 9 cout << "Person析构函数的调用"<< endl; 10 }
总结:如果属性有在堆区开辟的,一定要自己提供拷贝构造函数,防止浅拷贝带来的问题
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)