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

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

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

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++ class
个人分类: C/C++ 语言
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

不良信息举报

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

最多只允许输入30个字

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭