永发信息网

C++下对象的赋值和复制的具体区别?

答案:2  悬赏:20  手机版
解决时间 2021-02-01 07:34
RT
最佳答案
赋值时存在一个对象的实例;如 int a = 10;只有a这一个对象实例;赋值时存在两个对象的实例;如 int a = b;存在a和b这两个对象的实例;
全部回答
拷贝构造函数,是一种特殊的构造函数,它由编译器调用来完成一些基于同一类的其他对象的构建及初始化。其唯一的参数(对象的引用)是不可变的(const类型)。此函数经常用在函数调用时用户定义类型的值传递及返回。拷贝构造函数要调用基类的拷贝构造函数和成员函数。如果可以的话,它将用常量方式调用,另外,也可以用非常量方式调用。 目录 拷贝构造函数说明 一、拷贝函数 二、值的重载 三、注意事宜 四、拷贝构造与构造区别 展开 编辑本段 拷贝构造函数说明 调用拷贝构造函数的情形 在C++中,下面三种对象需要调用拷贝构造函数: 1) 一个对象以值传递的方式传入函数体; 2) 一个对象以值传递的方式从函数返回; 3) 一个对象需要通过另外一个对象进行初始化; 如果在前两种情况不使用拷贝构造函数的时候,就会导致一个指针指向已经被删除的内存空间。对于第三种情况来说,初始化和赋值的不同含义是构造函数调用的原因。事实上,拷贝构造函数是由普通构造函数和赋值操作符共同实现的。描述拷贝构造函数和赋值运算符的异同的参考资料有很多。 拷贝构造函数不可以改变它所引用的对象,其原因如下:当一个对象以传递值的方式传一个函数的时候,拷贝构造函数自动的被调用来生成函数中的对象。如果一个对象是被传入自己的拷贝构造函数,它的拷贝构造函数将会被调用来拷贝这个对象这样复制才可以传入它自己的拷贝构造函数,这会导致无限循环直至栈溢出(Stack Overflow)。除了当对象传入函数的时候被隐式调用以外,拷贝构造函数在对象被函数返回的时候也同样的被调用。 隐式的拷贝构造函数 如果在类中没有显式的声明一个拷贝构造函数,那么,编译器会自动生成一个来进行对象之间的位拷贝(Bitwise Copy)。这个隐含的拷贝构造函数简单的关联了所有的类成员。注意到这个隐式的拷贝构造函数和显式声明的拷贝构造函数的不同在于对成员的关联方式。显式声明的拷贝构造函数关联的只是被实例化的类成员的缺省构造函数,除非另外一个构造函数在类初始化或构造列表的时候被调用。 拷贝构造函数使程序更有效率,因为它不用再构造一个对象的时候改变构造函数的参数列表。设计拷贝构造函数是一个良好的风格,即使是编译系统会自动为你生成默认拷贝构造函数。事实上,默认拷贝构造函数可以应付许多情况。 示例 以下讨论中将用到的例子: 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.Init(40); //现在需要另一个对象,需要将他初始化称对象一的状态 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传给构造函数,以用来作复制。原则上,应该为所有包含动态分配成员的类都提供拷贝构造函数。 下面介绍拷贝构造函数的另一种调用。当对象直接作为参数传给函数时,函数将建立对象的临时拷贝,这个拷贝过程也将调同拷贝构造函数。例如: 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原有内容的丢弃,新内容的复制。 但"="的缺省操作只是将成员变量的值相应复制。旧的值被自然丢弃。 由于对象内包含指针,将造成不良后果:指针的值被丢弃了,但指针指向的内容并未释放。指针的值被复制了,但指针所指内容并未复制。 因此,包含动态分配成员的类除提供拷贝构造函数外,还应该考虑重载"="赋值操作符号。 类定义变为: class CExample { ... CExample(const CExample&); //拷贝构造函数 CExample& operator = (const CExample&); //赋值符重载 ... }; //赋值操作符重载 CExample & CExample::operator = (const CExample& RightSides) { if (this == &RightSides) // 如果自己给自己赋值则直接返回 { return *this; } nSize=RightSides.nSize; //复制常规成员 char *temp=new char[nSize]; //复制指针指向的内容 memcpy(temp,RightSides.pBuffer,nSize*sizeof(char)); delete []pBuffer; //删除原指针指向内容(将删除操作放在后面,避免X=X特殊情况下,内容的丢失) pBuffer=NULL; pBuffer=temp; //建立新指向 return *this } 编辑本段 三、注意事宜 拷贝构造函数和赋值函数的功能是相同的,为了不造成重复代码,拷贝构造函数实现如下: CExample::CExample(const CExample& RightSides) { *this=RightSides; //调用重载后的"=" } 编辑本段 四、拷贝构造与构造区别 class 类名 { public: 类名(形参参数)//构造函数 类名(类名&对象名)//拷贝构造函数 ,,,,,,,,,,,,,,,,,,,,, }; 拷贝构造函数的实现: 类名::类名(类名&对象名)//拷贝构造函数的实现 {函数体} 不完整的例子 拷贝构造函数: Class Point { Public: Point(int xx=0,int yy=m)(X=xx;Y=yy;) Point(Point& p); Int getX() {return X;} Int getY(){ return Y;} Private : Int X,Y; } Point::Point(Point& p) { X=p.X; Y=p.Y; Cout<<"拷贝构造函数调用"<<endl; }
我要举报
如以上问答信息为低俗、色情、不良、暴力、侵权、涉及违法等信息,可以点下面链接进行举报!
大家都在看
黄石港区黄石顺缘公寓我想知道这个在什么地方
我想买个车 都说网上车贷计算器与现实有差别
河清兵士的意思是什么啊?知道的请说下!
一般配眼镜都是以镜片的中心看出去最清楚,那
买的房子顶不平,用石膏板吊顶的话石膏板离房
渑池县三门峡渑池县天池镇文化站这个地址怎么
中国最先进的导弹有哪些?
常用的钢卷尺的分度值和量程分别是多少
胡萝卜中间发紫能吃吗?
松滋市荆州亚平乒乓球馆地址在哪,我要去那里
银字儿的意思是什么啊?知道的请说下!
没独显能装win10吗
我的信用坏了,但是想申请张信用卡
医保报销有上限吗
蒸湘区衡阳波波美容(中泰店)地址在哪里啊
推荐资讯
我家的狗狗不愿意让人给它拔耳毛,去抓它的时
材料一:全国第四届道德模范评选表彰颁奖典礼
东东幼教生活馆地址在什么地方,我要处理点事
如梦苑养生会所地址在什么地方,想过去办事
弘善堂地址在什么地方,我要处理点事
以下围护结构的厚度相同,哪种材料的传热系数
季风时尚造型(五马祠)地址在哪,我要去那里办
标致308s怎么调节大灯高度
抵死食鸡脾 白话是什么意思啊
feelunique容易被税吗
银魂中的大战新八的哥哥
丁某,女,41岁。疟疾迁延日久,每遇劳累辄易
正方形一边上任一点到这个正方形两条对角线的
阴历怎么看 ?