为什么这里不调用复制构造函数

Why is copy constructor not called here?

本文关键字:复制 构造函数 调用 这里 为什么      更新时间:2023-10-16

我正在快速C++复习课程。 试图复习一些基本概念。 当我运行以下程序时,我看到两个问题:1. 由于某种原因,没有调用复制 CC。2. 函数 testCC() 退出后,程序由于某种原因崩溃。

任何帮助不胜感激!

class A
{
public:
    A() 
    {
        this->ptr = new int[10];
    }
    ~A()
    {
        delete[] ptr;
    }
    A(const A &obj)
    {
        std::cout << "Copy CC calledn";
        for (int i = 0; i < 10; i++)
        {
            ptr[i] = obj.ptr[i];
        }
    }
    void set()
    {
        for (int i = 0; i < 10; i++)
        {
            ptr[i] = rand() % 10;
        }
    }
    void print()
    {
        for (int i = 0; i < 10; i++)
        {
            std::cout << ptr[i] << " ";
        }
        std::cout << "n";
    }
private:
    int *ptr;
};
void testCC()
{
    A a1,a2;
    a1.set();
    std::cout << "Contents of a1n";
    a1.print();
    a2 = a1;
    std::cout << "Contents of a2n";
    a2.print();
}

复制赋值和复制构造不是一回事。

a2 = a1调用a2.operator=(a1)(复制赋值),而不是复制构造函数。 您可以在 A 类中像这样定义复制赋值运算符:

A & operator=(A const & obj)
{
    // Perform copy...
    return *this;
}

无论哪种方式,您的复制构造函数都是错误的(您在使用它之前不会初始化ptr),因此即使使用了您的复制构造函数,您也会调用未定义的行为并可能崩溃。

问题,我相信是这一行:

a2 = a1;

此行不调用 A 的复制构造函数,因为 a2 已存在。 (目前尚未构建它。 相反,它调用 A 的赋值运算符:A& operator=(const A&)

由于尚未定义赋值运算符,因此将获得默认编译器生成的赋值运算符,该运算符仅执行按位复制。 因此,a2 和 a1 最终都包含相同的ptr值。 这也是您的程序崩溃的原因。 当testCC退出时,a1 和 a2 都会被销毁,并且都试图释放同一个数组。

>a2 = a1调用复制赋值运算符,而不是复制构造函数。您的类没有实现复制赋值运算符,因此编译器会生成一个默认运算符,该运算符仅执行成员级复制。a1 = a2后,您有两个指向同一内存的ptr副本,当testCC返回时,ab都会尝试删除这些副本。此双重删除导致崩溃。

可以通过编写A a2(a1)A a2 = a1来测试复制构造函数

a2 = a1;

是作业而不是复制。

A a3 = a1;

这将调用复制构造函数。

编写赋值运算符

A & operator=(const A & obj)
{
    std::cout << "Assingment calledn";
    for (int i = 0; i < 10; i++)
    {
        ptr[i] = obj.ptr[i];
    }
    return *this;
}

这将由

a2 = a1;

这不会调用复制构造函数,因为它是一个构造函数,应该在创建对象并且已经创建了 a2 时调用。

崩溃的

可能原因可能是在testCC之后,当调用析构函数时,a1的析构函数将释放指针,但由于a2的指针也指向同一位置,在析构函数中删除它时,它会崩溃。

因此,在复制任何内容之前始终构造对象。