📌  相关文章
📜  我们什么时候应该编写自己的副本构造函数?(1)

📅  最后修改于: 2023-12-03 15:25:41.996000             🧑  作者: Mango

当应该编写自己的副本构造函数?

在大多数情况下,C++ 的默认复制构造函数会足够满足我们的需求。但在某些情况下,我们可能需要编写自己的副本构造函数。

什么是副本构造函数?

副本构造函数是一种特殊的成员函数,它用于在创建对象的新副本时执行必要的内存和资源分配操作。当我们创建一个新对象并将其初始化为另一个对象的副本时,编译器会调用副本构造函数。

何时需要编写自己的副本构造函数?

下面是一些情况下,我们可能需要编写自己的副本构造函数。

类包含裸指针

当我们的类包含裸指针时,复制对象可能会导致内存泄漏或段错误。这是因为默认的复制构造函数只会简单地复制指针的值,而没有复制指针所指向的数据。为了避免这种情况,我们需要编写自己的副本构造函数来复制指针所指向的数据。

class MyClass {
public:
    MyClass();
    MyClass(const MyClass& other);
    ~MyClass();
private:
    int* m_ptr;
};

MyClass::MyClass() {
    m_ptr = new int;
}

MyClass::MyClass(const MyClass& other) {
    m_ptr = new int;
    *m_ptr = *(other.m_ptr);
}

MyClass::~MyClass() {
    delete m_ptr;
}
类含有资源

如果我们的类含有比如 mutex 等资源,那么在复制对象时会导致不必要的麻烦。在这种情况下,我们需要编写自己的副本构造函数,以确保资源得到正确的分配和释放。

class MyClass {
public:
    MyClass();
    MyClass(const MyClass& other);
    ~MyClass();
private:
    std::mutex m_mutex;
};

MyClass::MyClass() {
    // Do nothing
}

MyClass::MyClass(const MyClass& other) {
    // Acquire the mutex in the other object
    other.m_mutex.lock();
    // Copy the member variables
    // ...
    // Release the mutex in the other object
    other.m_mutex.unlock();
}

MyClass::~MyClass() {
    // Do nothing
}
类含有不可复制成员变量

如果我们的类有一个成员变量是不可复制的,也就是说,它的副本构造函数是私有的或被删除的,那么我们需要为类编写自己的副本构造函数。

class NonCopyable {
public:
    NonCopyable() {}
    NonCopyable(const NonCopyable&) = delete;
    NonCopyable& operator=(const NonCopyable&) = delete;
};

class MyClass {
public:
    MyClass();
    MyClass(const MyClass& other);
    ~MyClass();
private:
    NonCopyable m_nc;
};

MyClass::MyClass() {
    // Do nothing
}

MyClass::MyClass(const MyClass& other) {
    // Copy the member variables except m_nc
    // ...
}

MyClass::~MyClass() {
    // Do nothing
}
总结

在需要执行特殊操作或处理特殊情况的情况下,我们需要编写自己的副本构造函数。但是,在大多数情况下,我们可以信任默认的复制构造函数。