C++ 笔记 拷贝构造函数 深拷贝 浅拷贝(面向对象)

发布时间:2026/7/24 6:22:32

C++ 笔记 拷贝构造函数 深拷贝 浅拷贝(面向对象) 在 C 面向对象编程中拷贝构造函数是对象拷贝的核心机制而浅拷贝与深拷贝是拷贝构造函数最核心的两个概念也是新手最容易踩坑的知识点。本文将从定义、用法、区别、实战场景全面讲解帮你彻底掌握这一关键内容。一、拷贝构造函数是什么1. 基本定义拷贝构造函数是 C 类的特殊构造函数作用是用一个已经存在的对象初始化另一个同类型的新对象。它的固定语法格式类名(const 类名 源对象);1.函数名必须和类名完全一致2.参数必须是当前类的 const 引用使用 const 保证源对象不被修改使用引用避免无限递归调用3.没有返回值。2. 拷贝构造函数的调用时机只要是用旧对象初始化新对象就会自动调用拷贝构造函数常见 3 种场景用已存在的对象创建新对象类名 新对象(旧对象);函数的形参是类的对象值传递函数的返回值是类的对象值返回。3. 默认拷贝构造函数如果我们没有手动编写拷贝构造函数C 编译器会自动生成一个默认拷贝构造函数。这个默认函数的行为很简单逐字节拷贝对象的成员变量这就是浅拷贝。二、浅拷贝Shallow Copy1. 浅拷贝的特点由编译器默认生成的拷贝构造函数实现仅拷贝对象的成员变量值不拷贝指针指向的堆内存数据多个对象共用同一块堆内存空间。2. 浅拷贝代码示例#include iostream #include cstring using namespace std; class Student { private: char* name; // 指针成员指向堆内存 int age; public: // 普通构造函数 Student(const char* n, int a) { age a; // 为name在堆上分配内存 name new char[strlen(n) 1]; strcpy(name, n); cout 调用普通构造函数 endl; } // 析构函数释放堆内存 ~Student() { if (name ! NULL) { delete[] name; name NULL; cout 调用析构函数释放堆内存 endl; } } // 打印信息 void showInfo() { cout 姓名 name 年龄 age endl; } }; int main() { Student s1(张三, 20); Student s2 s1; // 调用编译器默认拷贝构造函数浅拷贝 s1.showInfo(); s2.showInfo(); return 0; }3. 浅拷贝的致命问题运行上述代码程序会崩溃原因默认拷贝构造函数只拷贝了name指针的地址值没有重新分配堆内存s1和s2的name指针指向同一块堆内存程序结束时s2先调用析构函数释放内存s1再次调用析构函数会对同一块内存重复释放导致程序崩溃。这就是浅拷贝最大的坑指针成员浅拷贝会造成堆内存重复释放、数据污染。三、深拷贝Deep Copy1. 深拷贝的特点必须手动编写拷贝构造函数实现不仅拷贝成员变量的值还会为指针成员重新分配堆内存并拷贝原数据每个对象拥有独立的堆内存空间互不干扰。2. 深拷贝代码示例解决浅拷贝问题我们手动实现拷贝构造函数完成深拷贝#include iostream #include cstring using namespace std; class Student { private: char* name; int age; public: // 普通构造函数 Student(const char* n, int a) { age a; name new char[strlen(n) 1]; strcpy(name, n); cout 调用普通构造函数 endl; } // 手动实现拷贝构造函数深拷贝核心 Student(const Student s) { age s.age; // 关键重新分配堆内存再拷贝数据 name new char[strlen(s.name) 1]; strcpy(name, s.name); cout 调用拷贝构造函数深拷贝 endl; } // 析构函数 ~Student() { if (name ! NULL) { delete[] name; name NULL; cout 调用析构函数 endl; } } void showInfo() { cout 姓名 name 年龄 age endl; } }; int main() { Student s1(张三, 20); Student s2 s1; // 调用手动编写的深拷贝构造函数 s1.showInfo(); s2.showInfo(); return 0; }运行结果程序正常运行无崩溃两个对象的name拥有独立的堆内存析构时各自释放互不影响。四、浅拷贝 vs 深拷贝 核心对比表格特性浅拷贝深拷贝实现方式编译器默认生成手动编写拷贝构造函数指针成员处理仅拷贝指针地址共享堆内存重新分配堆内存拷贝数据内存问题重复释放堆内存、程序崩溃内存独立无安全问题适用场景类中无指针 / 堆内存成员类中有指针 / 堆内存成员效率高仅拷贝值较低需分配内存 拷贝数据五、核心总结拷贝构造函数用于旧对象初始化新对象无手动实现则编译器生成默认版本浅拷贝默认行为只拷贝成员值有指针成员时绝对不能用会造成内存泄漏 / 程序崩溃深拷贝手动实现为指针成员重新分配内存是处理带堆内存对象的唯一安全方案黄金法则只要类中有指针成员、动态分配内存new/malloc就必须手动实现拷贝构造函数做深拷贝。掌握这三个知识点是 C 面向对象编程中避免内存错误、写出稳定代码的基础。总结拷贝构造函数用于对象初始化无自定义实现时编译器会生成默认版本浅拷贝仅拷贝成员值指针成员会共享堆内存极易引发程序崩溃深拷贝需手动实现为指针成员独立分配内存是带堆内存对象的安全拷贝方式。

相关新闻