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