为什么需要复制构造函数,它们在什么情况下非常有用?

why are copy constructors needed and what are the cases where they are very helpful?

为什么我们需要复制构造函数?

我正在学习 C++,但我无法理解复制构造函数的必要性,因为在不使用复制构造函数的情况下,我也得到了正确的输出。 我经历了几个例子,但在我看来,拥有复制构​​造函数只是一种很好的做法,比如初始化变量。有人可以帮助我理解复制构造函数的概念。 非常感谢任何帮助。 谢谢。

如果您通过复制传递将对象传递给方法,C++ 必须使用复制构造函数为方法上下文生成 class 的实例。例如,如果您将实例存储在向量中,当您推回一个对象时,它会间接调用复制构造函数。顺便说一下,对于 classes,如果没有显式实现的复制构造函数,c++ 通常会创建一个默认的复制构造函数,这种情况有时会产生不需要的效果(浅复制)。

让我们看下一个例子

#include <iostream>
struct A {
    explicit A(int value) : data_(new int[1]) { data_[0] = value; }
    ~A() { delete [] data_; }

    int getValue() const { return data_[0]; }

  private:
    int *data_ = nullptr;
};

int main() {
    A a1(1);
    A a2(2);
    a2 = a1;
    std::cout << a2.getValue() << std::endl;
}

如果你执行它,程序会崩溃。

这里发生的是您将 int *data_ 字段从 a1 复制到 a2,然后由 a2 分配的内存被泄漏。

现在 a1a2 有相同的指针。他们都将调用析构函数来释放内存。内存会被释放两次,导致崩溃。

提供正确的复制构造函数将解决此问题。

三的法则(也称为三巨头法则或三巨头)是 C++(C++11 之前)中的一条经验法则,声称如果 class 定义以下任何一项,那么它可能应该明确定义所有三个:析构函数。复制构造函数。复制赋值运算符。

要点:当您在对象构造函数中进行动态内存分配(堆)时,复制构造函数是必需的,您还需要将分配的内存复制到新分配的对象。这样你就可以 (Obj1 = Obj2 / Obj1(Obj2) ) 并保证动态内存也将被复制。

because without using a copy constructor also, we can get the desired output

事实并非如此。您没有编写复制构造函数,但您通过编译器为您编写的复制构造函数获得了所需的输出:

If no user-defined copy constructors are provided for a class type (struct, class, or union), the compiler will always declare a copy constructor as a non-explicit inline public member of its class

有关隐式声明的复制构造函数的更多详细信息,请参见https://en.cppreference.com/w/cpp/language/copy_constructor


简而言之,复制构造函数是在复制 class 实例时调用的函数。编译器为您编写它,但如果您希望它做一些重要的事情,您可以自己编写它(例如不是复制指针而是复制它指向的对象)