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++ primer 学习笔记:复制控制之赋值操作符

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

C++ Primer 学习笔记_54_类与数据抽象 -复制构造函数、赋值操作符

复制控制 --复制构造函数、赋值操作符 引言:    当定义一个新类型时,需要显式或隐式地指定复制、赋值和撤销该类型的对象时会发生什么– 复制构造函数、赋值操作符...

C++ Primer 学习笔记_16_表达式 --算术、关系、逻辑、位、赋值、自增/自减操作符

表达式 --算术关系逻辑位赋值自增自减操作符 引正文 表达式 --算术、关系、逻辑、位、赋值、自增/自减操作符 引:    除了特殊用法,表达式的结果为右值:可以读取结果值,但是不能...

C++语法基础--复制控制--复制构造函数 ,赋值操作符 ,析构函数

复制控制(编译器自动实现这些操作)             *复制构造函数             *赋值操作符              *析构函数          1.复...

一个实例介绍C++复制控制(有一个C++11新特性要注意)——复制构造函数、赋值操作符、析构函数

复制构造函数

C++ Primer学习笔记——$14 操作符重载、函数对象及类类型转换

题记:本系列学习笔记(C++ Primer学习笔记)主要目的是讨论一些容易被大家忽略或者容易形成错误认识的内容。只适合于有了一定的C++基础的读者(至少学完一本C++教程)。  作者: tyc611,...
  • whycold
  • whycold
  • 2011年01月19日 15:09
  • 726

C++ Primer 4 第十四章 重载操作符与转换

第十四章 重载操作符与转换 1. 重载操作符的定义          重载操作符是具有特殊名称的函数:保留字 operator 后接需定义的操作符号。像任意其他函数一样,重载操作符具有返回类型和形...

C++ Primer笔记(十二)重载操作符与转换

重载操作符必须具有至少一个类类型或枚举类型的操作数,这条规则强制重载操作符不能重新定义用于内置类型 对象的操作符含义。 重载操作符时使用默认实参是非法的。 大多数重载操作符可以定义为普通...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:C++ Primer复制控制 13.2 赋值操作符
举报原因:
原因补充:

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