分类: C/C++
2013-03-07 17:46:50
先上一个小例子
class Fx
{
public:
char *m_data;
};
void foo(Fx fx)
{
}
int main (void)
{
Fx fx;
fx.m_data = new char[10];
foo(fx);
delete fx.m_data;
return 0;
}
很简单,一个简简单单的类,和调用,没有错,正常运行,没有指针错误,没有内存错误
也是很多同学用经常用的
接下来,我们想把类更完善一点,让调用的人,不用去管内存分配,不用去释放内存,下面我们写:
class Fx
{
public:
char *m_data;
Fx();
~Fx();
};
Fx::Fx()
{
m_data = new char[10];
}
Fx::~Fx()
{
delete m_data;
}
void foo(Fx fx)
{
}
int main (void)
{
Fx fx;
foo(fx);
return 0;
}
我们把类的构造函数和析构函数重写,初始化了变量m_data, 在结束时释放了内存。
一切看起来都那么的完美。
真的么? 下面是见证奇迹的时刻:
如果没有函数
void foo(Fx fx)
{
}
那么它很正确,没问题,但是这样调用之后,问题来了。
这里用了浅拷贝,当数据成员中没有指针时,各自管各自的内存,互不干扰。
可有指针时,他们指向的地址将是一样的,在其它地方把实例数据修改后,传入foo中的数据,就不是我们想要的了。而且,其中一个删除,而另外一个没有操作,指针就变成了野指针,问题大大的……
解决的办法 ?
改一下,我们不能改类模块时,只能修改调用
为了安全,我们建议传递参数时用传引用,这也是传引用与传址、传值的区别之一
void foo(Fx &fx)
{
}
这样,安全。或者你不让调用的函数里修改它,用const 也是一个权宜之计,可是我要修改呢?
麻烦……
类不安全,调用的人付责任,有点过分
class Fx
{
public:
char *m_data;
Fx();
Fx(const Fx& fx);
~Fx();
};
Fx::Fx()
{
m_data = new char[10];
}
Fx::Fx(const Fx fx)
{
m_data = new char[10];
memcpy(m_data,fx.m_data,10);
}
Fx::~Fx()
{
delete m_data;
}
void foo(Fx &fx)
{
}
int main (void)
{
Fx fx;
foo(fx);
return 0;
}
加入拷贝构造函数,拷贝时,自己用自己的内存,这下没话说了,你随便调用,传值、传址、传引用……。
路漫漫,大学时还觉得指针简单……
就和刀一样,铁片一块,用的不好,砍柴伐树,用的好一代宗师……
后话:
深拷贝与浅拷贝的区别就在于深拷贝会在堆内存中另外申请空间来储存数据,指针悬挂的问题。
简而言之,当数据成员中有指针时,必须要用深拷贝。