这篇文章写了两个初级程序员不注意的问题,但这两个问题却很严重。
一. 在写类的时候,很多时候都会用到另一个类对象的指针。在以下三种情况下:
1.给一个类对象初始化时,例如:
A a; A b = a; 声明A类的另一个对象b用原来的a对象初始化
2.对象作为函数参数时,
3.函数返回一个对象时。
会调用类的拷贝构造函数。而如果程序开发者不显示定义拷贝构造函数,那么编译器将调用默认的拷贝构造函数,而这个默认的拷贝构造函数只起到一个浅拷贝的作用。
对于类中指向其他类对象的指针这种情况,不能达到深拷贝。对于不能进行深拷贝的指针对象将来会发生两个类共用一个指向的资源。当改变或删除这个共同资源时,
在使用这个资源时会发生错误,并且如果指针在构造函数中动态申请了内存,还会造成内存泄露。
正确
class A
{
public:
A()
{
pB = new B();
}
A(const A& a)
{
pB = NULL;
*this = a;
}
const A& operator = (const A& a)
{
this->Aa = a.Aa;
B* pTempB = new B();
*pTempB = *a.pB;
delete this->pB; //避免内存泄露
this->pB = pTempB;
return *this;
}
~A()
{
delete pB;
pB = NULL;
}
public:
B* GetpB() const
{
return pB;
}
private:
B* pB;
int Aa;
};
class B
{
public:
B();
~B();
public:
int Ba;
char t;
};
注意:A a; A c; c = a;和 A a; A c = a;的区别。前者先是声明了两个对象后再赋值,= 会调用重载的 = ,后者是在声明对象c的同时给c初始化,此处会调用拷贝构造函数。
建议:http://www.vckbase.com/document/viewdoc/?id=788这篇文章写的挺好的,什么时候需要显示定义拷贝构造函数,什么时候需要重载=(赋值操作符)。
还有在《c++Primer中文版(第四版)》中的第十三章中也较深入的写了关于“复制控制”。
二. 初级程序员还应该注意的另一个问题是:在类继承的时候要使用虚析构函数,因为如果不使用虚析构,当你delete指针(指针定义为父类,但在某个过程中赋值为子类)时,
只能delete父类,子类不能得到删除,这样就造成了内存泄露,而且有可能很难查出来。
浙公网安备 33010602011771号