副本构造器(源自小甲鱼的C++快速入门)
在小甲鱼的C++快速入门当中,副本构造器那一课。为了避免“逐个复制”的问题,使用重构“=”赋值还有自己定义副本构造器的方法。仿造小甲鱼代码如下:#include <iostream>
class MyClass
{
public:
MyClass(int *p);
MyClass(const MyClass &rhs);
~MyClass();
MyClass & operator = (const MyClass &rhs);
void print();
private:
int *ptr;
};
MyClass::MyClass(int *p)
{
std::cout << "进入主构造器\n";
ptr = p;
std::cout << "离开主构造器\n";
}
MyClass::MyClass(const MyClass &rhs)
{
std::cout << "进入副本构造器\n";
*this = rhs;
std::cout << "离开副本构造器\n";
}
MyClass::~MyClass()
{
delete ptr;
}
MyClass & MyClass::operator = (const MyClass &rhs)
{
std::cout << "进入赋值语句重载\n";
if(this != &rhs)
{
delete ptr; //必须先删除之前的内存
ptr = new int;
*ptr = *(rhs.ptr);
}
std::cout << "离开赋值语句重载\n";
return *this;
}
void MyClass::print()
{
std::cout << *ptr <<"\n";
}
int main()
{
MyClass obj3(new int(3));
MyClass obj4 = obj3;
obj3.print();
obj4.print();
std::cin.get();
return 0;
}
应该是没有问题的,但是运行总是出错,出错语句:
MyClass & MyClass::operator = (const MyClass &rhs)
{
std::cout << "进入赋值语句重载\n";
if(this != &rhs)
{
delete ptr; //总是在此处出错
ptr = new int;
*ptr = *(rhs.ptr);
}
std::cout << "离开赋值语句重载\n";
return *this;
}各位请帮帮忙啊~
你的 MyClass obj4 = obj3;这句话说明obj4里面的int*ptr没有申请过内存,那么当你delete ptr的时候肯定就要报错啰。 MyClass obj3(new int(3));
这句使得obj3.ptr指向动态分配出来的空间(为方便描述,称之为空间A)
MyClass obj4 = obj3;
这句使得obj4.ptr也指向空间A
obj4对象消亡的时候会释放空间A。
obj3对象消亡的时候企图再次释放空间A,所以报错
本质原因是副本构造函数写得有问题,应该使用深拷贝而非浅拷贝(若看不懂“深拷贝”和“浅拷贝”请自行baidu) 仰望天上的光 发表于 2015-1-3 13:10
MyClass obj3(new int(3));
这句使得obj3.ptr指向动态分配出来的空间(为方便描述,称之为空间A)
MyClas ...
但是我已经对“=”赋值语句进行了重载,MyClass & MyClass::operator = (const MyClass &rhs)
{
std::cout << "进入赋值语句重载\n";
if(this != &rhs)
{
delete ptr; //必须先删除之前的内存
ptr = new int;
*ptr = *(rhs.ptr);
}
std::cout << "离开赋值语句重载\n";
return *this;
}
这里指针已经不是指向同一个内存了,属于深拷贝。
但是我发现,将“delete ptr;”删掉就没有问题了。那么是不是可以解释成:在拷贝前,并没有生成obj4这个内存,但是却对其进行了删除,导致出错。我这样的解释对吗? Xiao_肚oO 发表于 2015-1-2 23:32
你的 MyClass obj4 = obj3;这句话说明obj4里面的int*ptr没有申请过内存,那么当你delete ptr的时候肯定就要 ...
恩恩,的确是这样的,看来源码就是有点问题,十分谢谢您。 清风袋袋 发表于 2015-1-3 21:12
但是我已经对“=”赋值语句进行了重载,
这里指针已经不是指向同一个内存了,属于深拷贝。
但是我发现 ...
你的程序根本没有使用到赋值运算符 MyClass obj4 = obj3;
这里调用的是拷贝构造函数而不是赋值运算符。 仰望天上的光 发表于 2015-1-4 10:58
MyClass obj4 = obj3;
这里调用的是拷贝构造函数而不是赋值运算符。
MyClass::MyClass(const MyClass &rhs)
{
std::cout << "进入副本构造器\n";
*this = rhs;
std::cout << "离开副本构造器\n";
}
副本构造器里面有调用吧?
MyClass obj4 = obj3;首先进入副本构造器,然后调用重载的“=”运算符,不是这样吗? 清风袋袋 发表于 2015-1-9 11:52
副本构造器里面有调用吧?
MyClass obj4 = obj3;首先进入副本构造器,然后调用重载的“=”运算符,不 ...
我运行了一下,没错啊 GRRRARD 发表于 2015-1-9 15:18
我运行了一下,没错啊
小甲鱼也没错。。。。就是在我这有错,哎,算了,这个问题。但其实理论上是有错的,需要改的~
页:
[1]