我正在进行快速课程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();
}
答案 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
副本指向同一个内存,a
和b
会在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>
因此,在复制任何内容之前总是构造对象。