C++ Primer复制控制 13.2 赋值操作符

转载 2016年06月01日 19:54:13

在面向对象程序设计中,对象间的相互拷贝和赋值是经常进行的操作。

如果对象在申明的同时马上进行的初始化操作,则称之为拷贝运算。例如:

class1 A("af"); class1 B=A;     

此时其实际调用的是B(A)这样的浅拷贝操作。   

如果对象在申明之后,在进行的赋值运算,我们称之为赋值运算。例如:       

class1 A("af"); class1 B;        

B=A;        

此时实际调用的类的缺省赋值函数B.operator=(A);        

不管是浅拷贝还是赋值运算,其都有缺省的定义。也就是说,即使我们不overload这两种operation,仍然可以运行。

那么,我们到底需不需要overload这两种operation 呢?        

答案就是:一般,我们我们需要手动编写析构函数的类,都需要overload 拷贝函数和赋值运算符。

note1:
    不要按值向函数传递对象。如果对象有内部指针指向动态分配的堆内存,丝毫不要考虑把对象按值传递给函数,要按引用传递。并记住:若函数不能改变参数对象的状态和目标对象的状态,则要使用const修饰符 

note2:问题:
    对于类的成员需要动态申请堆空间的类的对象,大家都知道,我们都最好要overload其赋值函数和拷贝函数。拷贝构造函数是没有任何返回类型的,这点毋庸置疑。 而赋值函数可以返回多种类型,例如以上讲的void,类本身class1,以及类的引用 class &? 问,这几种赋值函数的返回各有什么异同?
    答:1 如果赋值函数返回的是void ,我们知道,其唯一一点需要注意的是,其不支持链式赋值运算,即a=b=c这样是不允许的!
          2对于返回的是类对象本身,还是类对象的引用,其有着本质的区别!
              第一:如果其返回的是类对象本身
   A operator =(A& a)
    {
            if(name!=NULL)
                deletename;
        
this->_id=a._id;
        int len=strlen(a.name);
       name=new char[len+1];
        strcpy(name,a.name);
        return *this;
    }
          其过程是这样的:
                       class1A("herengnag");
                        class1B;   
                        B=A;
                    看似简单的赋值操作,其所有的过程如下:
                       1 释放对象原来的堆资源
                       2 重新申请堆空间
                       3 拷贝源的值到对象的堆空间的值
                       4 创建临时对象(调用临时对象拷贝构造函数),将临时对象返回
                       
5. 临时对象结束,调用临时对象析构函数,释放临时对象堆内存
my god,还真复杂!!
            但是,在这些步骤里面,如果第4步,我们没有overload 拷贝函数,也就是没有进行深拷贝。那么在进行第5步释放临时对象的heap 空间时,将释放掉的是和目标对象同一块的heap空间。这样当目标对象B作用域结束调用析构函数时,就会产生错误!!
            因此,如果赋值运算符返回的是类对象本身,那么一定要overload 类的拷贝函数(进行深拷贝)!
            第二:如果赋值运算符返回的是对象的引用,
   A& operator =(A& a)
    {
            if(name!=NULL)
                deletename;
        
this->_id=a._id;
        
int len=strlen(a.name);
       name=new char[len+1];
        strcpy(name,a.name);
        return *this;
    }
        那么其过程如下:
                   1释放掉原来对象所占有的堆空间
                   1.申请一块新的堆内存
                   2将源对象的堆内存的值copy给新的堆内存
                   3返回源对象的引用
                    4结束。
    因此,如果赋值运算符返回的是对象引用,那么其不会调用类的拷贝构造函数,这是问题的关键所在!!

C++复制构造函数与重载赋值操作符

http://www.cnblogs.com/BlueTzar/articles/1223313.html 复制构造函数是一种特殊的构造函数,函数的名称必须和类名称一致,它的唯一的一个参数是本类型的一...
  • qq_30230091
  • qq_30230091
  • 2015年07月30日 16:21
  • 1121

C++之派生类的拷贝构造与赋值运算符重载

这里只说一下为什么派生类在拷贝构造器和赋值运算符重载中一些注意语法: 一、派生类的拷贝构造器1.派生类的拷贝构造器跟普通构造器一样,若没有自定义生成,编译器会自动生成拷贝构造器,自动调用父类的拷贝构...
  • maoliran
  • maoliran
  • 2016年06月09日 19:28
  • 1682

c++ primer 学习笔记:复制控制之赋值操作符

赋值操作符 与类要控制初始化对象的方式一样,类也定义了该类型对象赋值时会发生什么:Sales_item trans, accum; trans = accum; 与复制构造函数一样,如果类没有定义自...
  • longhuaparty
  • longhuaparty
  • 2013年08月26日 22:52
  • 323

C++类的赋值运算符“=”重载,以及深拷贝和浅拷贝

C++类的赋值运算符“=”重载,以及深拷贝和浅拷贝 在面向对象程序设计中,对象间的相互拷贝和赋值是经常进行的操作。 如果对象在申明的同时马上进行初始化操作,则称之为拷贝运算。例如: class1 A(...
  • liubing8609
  • liubing8609
  • 2014年11月23日 14:51
  • 2696

C++运算符重载(8) - 默认赋值操作符和引用

前面的一篇文章已经讨论过了赋值操作符重载的问题,点此链接"C++运算符重载(3) - 什么时候需要自定义赋值操作符"。此篇文章是前一篇的扩展。在前面的这篇文章中,已经说过了什么当没有用户定义的赋值操作...
  • shltsh
  • shltsh
  • 2015年05月26日 09:57
  • 909

C++运算符重载(3) - 什么时候需要自定义赋值操作符

答案与拷贝构造函数一样。如果一个类不包含指针,则不需要自定义赋值操作符与拷贝构造函数。编译器会给每个类创建一个默认的拷贝构造函数和默认的赋值操作符。但是,当类中包含有指针或任何运行时分配的资源时,编译...
  • shltsh
  • shltsh
  • 2015年05月26日 09:32
  • 1071

C++ Primer学习总结 第13章 拷贝控制

第13章 拷贝控制 1.    什么是拷贝构造函数? P440 如果一个类的构造函数的第一个参数是自己类类型的引用, 且所有其他参数都有默认值, 那么这就是一个拷贝构造函数. ...
  • u013480600
  • u013480600
  • 2015年03月09日 10:33
  • 1429

C++ Primer(复制控制)

第13章 复制控制 复制构造函数、赋值操作符和析构函数总称为复制控制。 编译器自动实现这些操作,但类也可定义自己的版本。有一种特别常见的情况需要类定义自己的复制控制成员的:类具有指针成员。 13...
  • cfcf0517
  • cfcf0517
  • 2014年12月31日 13:35
  • 228

C++ Primer 复制控制

复制控制: 当定义一个新类型的时候,需要显式或隐式地指定复制、赋值和撤销该类型的对象时会发生什么——这是通过定义特殊成员:复制构造函数、赋值操作符和析构函数来达到的。如果没有显式定义复制构造函数或赋...
  • wangxueang224
  • wangxueang224
  • 2014年06月06日 20:00
  • 410

google C++ 编程规范中的禁用复制构造函数和赋值运算符

在google C++编程规范中有下面一段描述: 仅在代码中需要拷贝一个类对象的时候使用拷贝构造函数;不需要拷贝时应使用 DISALLOW_COPY_AND_ASSIGN。 定义:通过拷贝新...
  • SKY453589103
  • SKY453589103
  • 2016年03月02日 20:07
  • 401
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:C++ Primer复制控制 13.2 赋值操作符
举报原因:
原因补充:

(最多只允许输入30个字)