
【C/C++基础进阶系列】C/C++ 对象模型 -- 对象构造语义(二)
如果类没有定义拷贝构造函数。 类中包含一个类类型成员变量,该类有定义拷贝构造函数。 拷贝构造函数的合成生成:编译器会根据类的结构自动生成拷贝构造函数,适用于基本数据类型和嵌套对象的复制。 拷贝构造函数的调用时机:在拷贝赋值和内存管理时,拷贝构造函数会被调用以确保对象的正确复制。 深拷贝与浅拷贝的区别:深拷贝确保所有嵌套对象的复制,避免内存泄漏,而浅拷贝仅复制对象本身的值。 拷贝复制运算符的重要性:在资源管理和异常处理中,自定义拷贝构造函数和拷贝赋值运算符可以防止资源泄漏和数据不一致。
发布日期:2021-05-07 20:53:21
浏览次数:18
分类:精选文章
本文共 2660 字,大约阅读时间需要 8 分钟。
C++ 对象模型:拷贝构造函数的深度探讨
1. 拷贝构造函数的合成生成
在C++中,编译器会自动为类生成拷贝构造函数,但只有在特定情况下才会生效。以下是两种关键情况:
例如:
#includeusing namespace std;class A {public: int m_test;};int main() { A mya1; mya1.m_test = 15; A mya2 = mya1; return 0;}
此处,编译器会自动生成拷贝构造函数,负责复制基本数据类型的成员变量值。
当类包含复合对象(如ASon类和CTB类成员变量)时,编译器会递归复制每个成员变量的值。例如:
class ASon {public: int m_testson;};class A {public: int m_test; ASon asubobj; CTB m_ctb;};int main() { A mya1; mya1.m_test = 15; mya1.asubobj.m_testson = 120; A mya2 = mya1; return 0;}
编译器会为A类生成拷贝构造函数,调用CTB类的拷贝构造函数。
2. 拷贝构造函数的调用时机与作用
拷贝构造函数在以下情况下被调用:
- 当使用
=
操作符进行拷贝赋值时。 - 当使用
new
或delete
操作符进行内存管理时。
例如:
class X {public: int m_i; int* p_mi; X() { m_i = 0; p_mi = new int(100); cout << "X类的构造函数被调用" << endl; } X(const X& tmp) { m_i = tmp.m_i; cout << "X类的拷贝构造函数被调用" << endl; } ~X() { delete p_mi; cout << "X类的析构函数被调用" << endl; } X(int value) : m_i(value) { p_mi = new int(100); cout << "X类的X(int)构造函数被调用" << endl; }};int main() { X x0; x0.m_i = 150; X x1(x0); cout << x1.m_i << endl; return 0;}
输出:
150
3. 深拷贝与浅拷贝
浅拷贝仅复制对象的值,而不复制指向外部资源(如内存)的指针。深拷贝则确保所有嵌套对象也被复制。
例如:
class X {public: int m_i; int* p_mi; X() { m_i = 0; p_mi = new int(100); cout << "X类的构造函数被调用" << endl; } ~X() { delete p_mi; cout << "X类的析构函数被调用" << endl; } X(int value) : m_i(value) { p_mi = new int(100); cout << "X类的X(int)构造函数被调用" << endl; }};int main() { X x0; x0.m_i = 150; X x1(x0); // 浅拷贝:x1.m_i = 150 cout << x1.m_i << endl; return 0;}
此处,x1和x0的p_mi指向同一块内存。如果x0被释放,x1的p_mi指针将失效,导致内存泄漏。
4. 拷贝复制运算符与拷贝构造函数
默认情况下,C++支持对象的拷贝复制,但在某些情况下(如资源管理),需要自定义拷贝构造函数和拷贝赋值运算符。
例如:
#includeusing namespace std;class A {public: int m_i, m_j; A& operator=(const A& tmp) { m_i = tmp.m_i; m_j = tmp.m_j; cout << "A::operator=(const A&)拷贝赋值运算符执行了" << endl; return *this; } A(const A& tmp) { m_i = tmp.m_i; m_j = tmp.m_j; cout << "A::A(const A&)拷贝构造函数执行了" << endl; } A() { cout << "A::A()缺省构造函数执行了" << endl; }};int main() { A aobj; aobj.m_i = 15; aobj.m_j = 20; A aobj2 = aobj; A aobj3; aobj3.m_i = 13; aobj3.m_j = 16; aobj2 = aobj3; return 0;}
默认复制行为可以满足基本需求,但在资源管理和异常安全中,自定义拷贝构造函数和拷贝赋值运算符至关重要。
结论
通过上述内容,我们可以看到:
发表评论
最新留言
哈哈,博客排版真的漂亮呢~
[***.90.31.176]2025年03月24日 00时16分35秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
简单的xml读取存储方法(未优化)
2019-03-05
Nginx---惊群
2019-03-05
项目中常用的审计类型概述
2019-03-05
(九)实现页面底部购物车的样式
2019-03-05
python-day3 for语句完整使用
2019-03-05
ButterKnife使用问题
2019-03-05
为什么讨厌所谓仿生AI的说法
2019-03-05
ORACLE 客户端工具
2019-03-05
使用第三方sdk,微信wechat扫码登录
2019-03-05
基于LabVIEW的入门指南
2019-03-05
“/”应用程序中的服务器错误。
2019-03-05
weblogic之cve-2015-4852
2019-03-05
Java注释
2019-03-05
水调歌头·1024
2019-03-05
C++ 函数重载
2019-03-05
Nginx的Gzip功能
2019-03-05
abstract关键字的使用
2019-03-05
.NET微信网页开发之使用微信JS-SDK调用微信扫一扫功能
2019-03-05