深拷贝和浅拷贝
内容简介
浅拷贝是逐个成员复制;深拷贝是在复制指针指向的数据时重新申请资源。只要类中有裸指针管理堆资源,就必须认真区分这两者。
浅拷贝
默认拷贝构造通常是浅拷贝:
class Person {
public:
Person(int age, int height)
: age_(age), height_(new int(height))
{
}
~Person()
{
delete height_;
}
private:
int age_;
int* height_;
};如果这样拷贝:
Person p1(18, 160);
Person p2(p1);默认拷贝会让 p1.height_ 和 p2.height_ 指向同一块堆内存。两个对象析构时都会 delete 同一地址,导致重复释放。
深拷贝
自己实现拷贝构造,重新申请资源:
class Person {
public:
Person(int age, int height)
: age_(age), height_(new int(height))
{
}
Person(const Person& other)
: age_(other.age_), height_(new int(*other.height_))
{
}
Person& operator=(const Person& other)
{
if (this != &other) {
int* new_height = new int(*other.height_);
delete height_;
height_ = new_height;
age_ = other.age_;
}
return *this;
}
~Person()
{
delete height_;
}
private:
int age_;
int* height_;
};现代 C++ 推荐写法
优先避免裸指针资源:
class Person {
public:
Person(int age, int height)
: age_(age), height_(height)
{
}
private:
int age_;
int height_;
};如果确实需要动态资源,优先使用标准库类型:
class Buffer {
public:
explicit Buffer(std::size_t size) : data_(size) {}
private:
std::vector<std::byte> data_;
};最佳代码实践
- 类中有裸指针资源时,必须明确拷贝、赋值、析构、移动语义。
- 能用
std::string、std::vector、std::unique_ptr时,不要手写裸指针。 - 独占资源类通常禁止拷贝,允许移动。
- 共享资源时明确使用
std::shared_ptr,不要让裸指针表达共享所有权。
错误用法
class Person {
public:
int* height = new int(160);
};
Person p1;
Person p2 = p1; // 两个对象共享同一个指针,语义不清注意事项
学习路径
- 上一节:cpp拷贝构造函数调用时机
- 当前阶段:cppOOP
- 下一节:cpp初始化列表