为什么初始化时没有调用重载赋值运算符?



我创建了一个测试类来演示重载赋值运算符的使用,以及与双重释放内存相关的陷阱。此类的代码如下:

class Test {
public:
Test() : ptr{new int(0)}, val{0}, id{count++} {}
Test(int ptr_val, int new_val) : ptr{new int(ptr_val)}, val{new_val}, id{count++} {}
~Test()
{
delete ptr;
}
Test& operator=(const Test& rhs)
{
*ptr = *(rhs.ptr);
val = rhs.val;
}
void setPtrVal(int ptr_val)
{
*ptr = ptr_val;
}
void setVal(int new_val)
{
val = new_val;
}
void printData() const
{
cout << "id  = " << id  << endl;
cout << "val = " << val << endl;
cout << "ptr = " << ptr << endl;
cout << "*ptr = " << *ptr << endl << endl;
}
private:
int* ptr;
int val;
int id;
static int count;
};
int Test::count = 1;

我有两个主要函数,它们正在使用重载赋值运算符测试此类。我将每个主要函数的输出直接放在其正文下方。

主要 1:

int main()
{
Test t1;
Test t2(2, 2);
t1.printData();
t2.printData();
t2 = t1;  // Overloaded Assignment Operator
t1.printData();
t2.printData();
t2.setVal(3);
t2.setPtrVal(3);
t1.printData();
t2.printData();
return 0;
}

输出 1:(按预期工作(

id  = 1
val = 0
ptr = 0x204dc20
*ptr = 0
id  = 2
val = 2
ptr = 0x204dc40
*ptr = 2
id  = 1
val = 0
ptr = 0x204dc20
*ptr = 0
id  = 2
val = 0
ptr = 0x204dc40
*ptr = 0
id  = 1
val = 0
ptr = 0x204dc20
*ptr = 0
id  = 2
val = 3
ptr = 0x204dc40
*ptr = 3

主要 2:

int main()
{
Test t1(10, 15);
{
Test t2 = t1;
t2.printData();
}
t1.printData();
return 0;
}

输出 2(未按预期工作(:

id  = 1
val = 15
ptr = 0xd6fc20
*ptr = 10
id  = 1
val = 15
ptr = 0xd6fc20
*ptr = 0
*** Error in `./a.out': double free or corruption (fasttop): 0x0000000000d6fc20 ***

这很奇怪。出于某种原因,指针指向相同的内存,并且id字段相同。它应该是不同的。似乎调用了默认赋值运算符。我不知道为什么会这样。

不要试图批评程序本身。这只是出于教育目的的测试。我故意设置了这个,这样我就会有一个双重免费错误。重载赋值运算符旨在防止这种情况。它没有通过第二个测试...为什么会这样做?

这是因为初始化与赋值不同。因此,不会调用重载赋值运算符。复制构造函数在主 2 中被调用。由于此class Test未定义重载的复制构造函数,因此使用默认的复制构造函数,该构造函数逐个成员进行复制。

我将通过添加一个复制构造函数来演示它:

class Test {
public:
Test() : ptr{new int(0)}, val{0}, id{count++} {}
Test(int ptr_val, int new_val) : ptr{new int(ptr_val)}, val{new_val}, id{count++} {}
~Test()
{
delete ptr;
}
Test(const Test& rhs) : ptr{new int( *(rhs.ptr)  )}, val{rhs.val}, id{count++}
{
cout << "copy constructor called" << endl;
}
Test& operator=(const Test& rhs)
{
*ptr = *(rhs.ptr);
val = rhs.val;
}
void setPtrVal(int ptr_val)
{
*ptr = ptr_val;
}
void setVal(int new_val)
{
val = new_val;
}
void printData() const
{
cout << "id  = " << id  << endl;
cout << "val = " << val << endl;
cout << "ptr = " << ptr << endl;
cout << "*ptr = " << *ptr << endl << endl;
}
private:
int* ptr;
int val;
int id;
static int count;
};
int Test::count = 1;

int main()
{
Test t1(10, 15);
{
Test t2 = t1;
t2.printData();
}
t1.printData();
return 0;
}

输出符合预期:

copy constructor called
id  = 2
val = 15
ptr = 0xea4c40
*ptr = 10
id  = 1
val = 15
ptr = 0xea4c20
*ptr = 10

相关内容

  • 没有找到相关文章

最新更新