关于拷贝结构函数和赋值运算符
副标题#e#
重点:包括动态分派成员的类 应提供拷贝结构函数,并重载"="赋值操纵符。
以下接头中将用到的例子:
class CExample
{
public:
CExample(){pBuffer=NULL; nSize=0;}
~CExample(){delete pBuffer;}
void Init(int n){ pBuffer=new char[n]; nSize=n;}
private:
char *pBuffer; //类的工具中包括指针,指向动态分派的内存资源
int nSize;
};
这个类的主要特点是包括指向其他资源的指针。
pBuffer指向堆中分派的一段内存空间。
一、拷贝结构函数
int main(int argc, char* argv[])
{
CExample theObjone;
theObjone.Init40);
//此刻需要另一个工具,需要将他初始化称工具一的状态
CExample theObjtwo=theObjone;
...
}
语句"CExample theObjtwo=theObjone;"用theObjone初始化theObjtwo。
其完成方法是内存拷贝,复制所有成员的值。
完成后,theObjtwo.pBuffer==theObjone.pBuffer。
即它们将指向同样的处所,指针固然复制了,但所指向的空间并没有复制,而是由两个工具共用了。这样不切合要求,工具之间不独立了,并为空间的删除带来隐患。
所以需要回收须要的手段来制止此类环境。
回首以下此语句的详细进程:首先成立工具theObjtwo,并挪用其结构函数,然后成员被拷贝。
可以在结构函数中添加操纵来办理指针成员的问题。
所以C++语法中除了提供缺省形式的结构函数外,还类型了另一种非凡的结构函数:拷贝结构函数,上面的语句中,假如类中界说了拷贝结构函数,这工具成立时,挪用的将是拷贝结构函数,在拷贝结构函数中,可以按照传入的变量,复制指针所指向的资源。
拷贝结构函数的名目为:结构函数名(工具的引用)
提供了拷贝结构函数后的CExample类界说为:
class CExample
{
public:
CExample(){pBuffer=NULL; nSize=0;}
~CExample(){delete pBuffer;}
CExample(const CExample&); //拷贝结构函数
void Init(int n){ pBuffer=new char[n]; nSize=n;}
private:
char *pBuffer; //类的工具中包括指针,指向动态分派的内存资源
int nSize;
};
CExample::CExample(const CExample& RightSides) //拷贝结构函数的界说
{
nSize=RightSides.nSize; //复制通例成员
pBuffer=new char[nSize]; //复制指针指向的内容
memcpy(pBuffer,RightSides.pBuffer,nSize*sizeof(char));
}
这样,界说新工具,并用已有工具初始化新工具时,CExample(const CExample& RightSides)将被挪用,罢了有工具用别名RightSides传给结构函数,以用来作复制。
原则上,应该为所有包括动态分派成员的类都提供拷贝结构函数。
#p#副标题#e#
拷贝结构函数的另一种挪用。
当工具直接作为参数传给函数时,函数将成立工具的姑且拷贝,这个拷贝进程也将调同拷贝结构函数。
譬喻
BOOL testfunc(CExample obj);
testfunc(theObjone); //工具直接作为参数。
BOOL testfunc(CExample obj)
{
//针对obj的操纵实际上是针对复制后的姑且拷贝举办的
}
尚有一种环境,也是与姑且工具有关的
当函数中的局部工具被被返回给函数调者时,也将成立此局部工具的一个姑且拷贝,拷贝结构函数也将被挪用
CTest func()
{
CTest theTest;
return theTest
}
二、赋值符的重载
下面的代码与上例相似
int main(int argc, char* argv[])
{
CExample theObjone;
theObjone.Init(40);
CExample theObjthree;
theObjthree.Init(60);
//此刻需要一个工具赋值操纵,被赋值工具的原内容被排除,并用右边工具的内容填充。
theObjthree=theObjone;
return 0;
}
也用到了"="号,但与"一、"中的例子并差异,"一、"的例子中,"="在工具声明语句中,暗示初始化。更多时候,这种初始化也可用括号暗示。
譬喻 CExample theObjone(theObjtwo);
而本例子中,"="暗示赋值操纵。将工具theObjone的内容复制到工具theObjthree;,这个中涉及到工具theObjthree原有内容的扬弃,新内容的复制。
但"="的缺省操纵只是将成员变量的值相应复制。旧的值被自然扬弃。
由于工具内包括指针,将造成不良效果:指针的值被扬弃了,但指针指向的内容并未释放。指针的值被复制了,但指针所指内容并未复制。
因此,包括动态分派成员的类除提供拷贝结构函数外,还应该思量重载"="赋值操纵标记。
类界说变为:
#p#分页标题#e#
class CExample
{
...
CExample(const CExample&); //拷贝结构函数
CExample& operator = (const CExample&); //赋值符重载
...
};
//赋值操纵符重载
CExample & CExample::operator = (const CExample& RightSides)
{
nSize=RightSides.nSize; //复制通例成员
char *temp=new char[nSize]; //复制指针指向的内容
memcpy(temp,RightSides.pBuffer,nSize*sizeof(char));
delete []pBuffer; //删除原指针指向内容 (将删除操纵放在后头,制止X=X非凡环境下,内容的丢失)
pBuffer=temp; //成立新指向
return *this
}
三、拷贝结构函数利用赋值运算符重载的代码。
CExample::CExample(const CExample& RightSides)
{
pBuffer=NULL;
*this=RightSides //挪用重载后的"="
}