欢迎来到天天文库
浏览记录
ID:62075478
大小:55.18 KB
页数:7页
时间:2021-04-16
《C本质:类的赋值运算符的重载以及深拷贝和浅拷贝.docx》由会员上传分享,免费在线阅读,更多相关内容在教育资源-天天文库。
1、C++本质:类的赋值运算符=的重载,以及深拷贝和浅拷贝C++本质:类的赋值运算符=的重载,以及深拷贝和浅拷贝关键词:构造函数,浅拷贝,深拷贝,堆栈(stack),堆heap,赋值运算符摘要: 在面向对象程序设计中,对象间的相互拷贝和赋值是经常进行的操作。 如果对象在申明的同时马上进行的初始化操作,则称之为拷贝运算。例如: class1A("af");class1 B=A; 此时其实际调用的是B(A)这样的浅拷贝操作。 如果对象在申明之后,在进行的赋值运算,我们称之为赋值运算。例如: class1A
2、("af");class1B; B=A; 此时实际调用的类的缺省赋值函数B.operator=(A); 不管是浅拷贝还是赋值运算,其都有缺省的定义。也就是说,即使我们不overload这两种operation,仍然可以运行。那么,我们到底需不需要overload这两种operation呢? 答案就是:一般,我们我们需要手动编写析构函数的类,都需要overload拷贝函数和赋值运算符。 下面介绍类的赋值运算符1.C++中对象的内存分配方式 在C++中,对象的实例
3、在编译的时候,就需要为其分配内存大小,因此,系统都是在stack上为其分配内存的。这一点和C#完全不同!千万记住:在C#中,所有类都是referencetype,要创建类的实体,必须通过new在heap上为其分配空间,同时返回在stack上指向其地址的reference. 因此,在C++中,只要申明该实例,在程序编译后,就要为其分配相应的内存空间,至于实体内的各个域的值,就由其构造函数决定了。 例如: class A{public: A() { name=newchar[1]; //These
4、codeisadded ByCR *name='/0'; } A(int id,char *t_name) { _id=id; name=new char[strlen(t_name)+1]; strcpy(name,t_name); } private: char*name; int_id;}int main(){A a(1,"herengang");A b;}在程序编译之后,a和b在stack上都被分配相应的内存大小。只不过对象a的域都被初始化,而b则
5、都为随机值。其内存分配如下:2.缺省情况下的赋值运算符 如果我们执行以下: b=a; 则其执行的是缺省定义的缺省的赋值运算。所谓缺省的赋值运算,是指对象中的所有位于stack中的域,进行相应的复制。但是,如果对象有位于heap上的域的话,其不会为拷贝对象分配heap上的空间,而只是指向相同的heap上的同一个地址。 执行b=a这样的缺省的赋值运算后,其内存分配如下: 因此,对于缺省的赋值运算,如果对象域内没有heap上的空间,其不会产生任何问题。但是,如果对象域内需要申请heap上的空间,那
6、么在析构对象的时候,就会连续两次释放heap上的同一块内存区域,从而导致异常。 ~A() { delete name; }3.解决办法--重载(overload)赋值运算符 因此,对于对象的域在heap上分配内存的情况,我们必须重载赋值运算符。当对象间进行拷贝的时候,我们必须让不同对象的成员域指向其不同的heap地址--如果成员域属于heap的话。 因此,重载赋值运算符后的代码如下:class A{public: A() { } A(int id,cha
7、r *t_name) { _id=id; name=new char[strlen(t_name)+1]; strcpy(name,t_name); } A& operator =(A& a)//注意:此处一定要返回对象的引用,否则返回后其值立即消失! { if(name!=NULL) deletename; this->_id=a._id; int len=strlen(a.name);
8、 name=new char[len+1]; strcpy(name,a.name); return *this
此文档下载收益归作者所有