贝利信息

c++如何拷贝构造和赋值 c++深拷贝与浅拷贝【核心】

日期:2026-01-04 00:00 / 作者:裘德小鎮的故事
拷贝构造与赋值本质不同:前者初始化新对象,后者为已存在对象赋值;深拷贝需独立复制堆内存以避免资源共享,浅拷贝仅复制指针值;现代C++应优先用RAII智能指针和容器替代裸指针。

拷贝构造和赋值在 C++ 中本质都是对象复制,但触发时机、语义责任和实现细节完全不同;深拷贝与浅拷贝的区别,核心在于是否对指针所指向的堆内存做独立副本 —— 这直接决定多个对象是否共享同一块动态资源,是资源管理正确性的分水岭。

拷贝构造:用一个已有对象初始化新对象

当定义新对象并用同类型对象初始化时调用,例如:T a; T b = a;func(a)(传值)、return a;(返回局部对象)。编译器默认生成的拷贝构造函数执行的是逐成员位拷贝(shallow copy)。

若类中含裸指针(如 int* p;),默认拷贝会让两个对象的 p 指向同一块堆内存 —— 后续析构时重复 delete 就会崩溃。

必须手动定义拷贝构造函数来实现深拷贝:

赋值运算符:已存在对象接收另一个对象的值

使用 = 对已构造对象赋值时调用,例如:a = b;。默认赋值运算符同样只做浅拷贝,且不处理自我赋值(a = a;)和原有资源释放问题。

手写赋值运算符需满足“三法则”(Rule of Three):只要写了拷贝构造、析构或赋值之一,通常三个都得自己写。典型实现模式:

深拷贝 vs 浅拷贝:关键在资源所有权

浅拷贝只是复制指针值,多个对象共用同一份堆内存 —— 简单但危险;深拷贝为每个对象创建独立副本 —— 安全但开销大、需手动管理。

判断是否需要深拷贝,看类是否拥有「独占性资源」:

现代 C++ 的推荐做法:避免裸指针 + 遵循 RAII

真正解决深浅拷贝难题的根本方法,不是写更复杂的拷贝函数,而是从设计上消除裸指针:

这样,默认生成的拷贝/赋值函数就天然安全,既无内存泄漏也无重复释放 —— 深浅拷贝之争自然消解。