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

时间:2015-01-24 06:23:54

标签: c++ copy-constructor

我正在进行快速课程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 called\n";
        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 a1\n";
    a1.print();
    a2 = a1;
    std::cout << "Contents of a2\n";
    a2.print();
}

5 个答案:

答案 0 :(得分:4)

复制分配和复制构造不是一回事。

a2 = a1正在调用a2.operator=(a1)(复制赋值),而不是复制构造函数。您可以在A类:

中定义这样的复制赋值运算符
A & operator=(A const & obj)
{
    // Perform copy...

    return *this;
}

无论哪种方式,你的拷贝构造函数都很糟糕(你在使用它之前不要初始化ptr)所以即使你的拷贝构造函数被使用,你也会调用未定义的行为并且可能会崩溃。 / p>

答案 1 :(得分:4)

问题,我相信是这一行:

a2 = a1;

这一行不会调用A的复制构造函数,因为a2已经存在。 (目前还没有构建它。)相反,它会调用A的赋值运算符:A& operator=(const A&)

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

答案 2 :(得分:2)

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

您可以撰写A a2(a1)A a2 = a1

来测试您的复制构造函数

答案 3 :(得分:1)

a2 = a1;

是作业而非复制。

A a3 = a1;

这将调用复制构造函数。

写一个赋值运算符

A & operator=(const A & obj)
{
    std::cout << "Assingment called\n";
    for (int i = 0; i < 10; i++)
    {
        ptr[i] = obj.ptr[i];
    }

    return *this;
}

这将由

调用
a2 = a1;

答案 4 :(得分:0)

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

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

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