C++赋值函数详解

赋值函数
        每个类只有一个赋值函数  
        由于并非所有的对象都会使用拷贝构造函数和赋值函数,程序员可能对这两个函数有些轻视。
    1,如果不主动编写拷贝构造函数和赋值函数,编译器将以“位拷贝”的方式自动生成缺省的函数。倘若类中含有指针变量,那么这两个缺省的函数就隐含了错误。
               以类String的两个对象a,b为例,假设a.m_data的内容为“hello”,b.m_data的内容为“world”。   
               现将a赋给b,缺省赋值函数的“位拷贝”意味着执行b.m_data = a.m_data。
               这将造成三个错误:             
                        一是b.m_data原有的内存没被释放,造成内存泄露;
                        二是b.m_data和a.m_data指向同一块内存,a或b任何一方变动都会影响另一方;
                        三是在对象被析构时,m_data被释放了两次。   
        2,拷贝构造函数和赋值函数非常容易混淆,常导致错写、错用。拷贝构造函数是在对象被创建时调用的,而赋值函数只能被已经存在了的对象调用。以下程序中,第三个语句和第四个语句很相似,你分得清楚哪个调用了拷贝构造函数,哪个调用了赋值函数吗?  
           String a(“hello”);   
             String b(“world”); 
             String c = a;   // 调用了拷贝构造函数,最好写成 c(a); 
          c = b;      // 调用了赋值函数   
               本例中第三个语句的风格较差,宜改写成String c(a) 以区别于第四个语句。   
        类String的拷贝构造函数与赋值函数   
 // 拷贝构造函数            
         String::String(const String &other)   
         {   
             int length = strlen(other.m_data);  // 允许操作other的私有成员m_data 
               m_data = new char[length+1];  
             strcpy(m_data, other.m_data);  
      }   
// 赋值函数   
      String & String::operator =(const String &other)   
       {  
                if(this == &other)          // (1) 检查自赋值
                          return *this;   
          delete [] m_data;            // (2) 释放自己原有的内存资源 
              int length = strlen(other.m_data);     // (3)分配新的内存资源,并复制内容
            m_data = new char[length+1];   
              strcpy(m_data, other.m_data);   
            
              return *this;              // (4)返回本对象的引用
   }   
      类String拷贝构造函数与普通构造函数的区别是:在函数入口处无需与NULL进行比较,这是因为“引用”不可能是NULL,而“指针”可以为NULL。 
   类String的赋值函数比构造函数复杂得多,分四步实现:   
                (1)第一步,检查自赋值。你可能会认为多此一举,难道有人会愚蠢到写出 a = a 这样的自赋值语句!的确不会。但是间接的自赋值仍有可能出现,例如   // 内容自赋值   b = a;   …   c = b;   …   a = c;   // 地址自赋值   b = &a;   …   a = *b;   也许有人会说:“即使出现自赋值,我也可以不理睬,大不了化点时间让对象复制自己而已,反正不会出错!”   他真的说错了。看看第二步的delete,自杀后还能复制自己吗?所以,如果发现自赋值,应该马上终止函数。注意不要将检查自赋值的if语句   if(this == &other)   错写成为   if( *this == other)   
               (2)第二步,用delete释放原有的内存资源。如果现在不释放,以后就没机会了,将造成内存泄露。   
               (3)第三步,分配新的内存资源,并复制字符串。注意函数strlen返回的是有效字符串长度,不包含结束符‘\0’。函数strcpy则连‘\0’一起复制。   
               (4)第四步,返回本对象的引用,目的是为了实现象 a = b = c 这样的链式表达。注意不要将 return *this 错写成 return this 。那么能否写成return other 呢?效果不是一样吗?       不可以!因为我们不知道参数other的生命期。有可能other是个临时对象,在赋值结束后它马上消失,那么return other返回的将是垃圾。   偷懒的办法处理拷贝构造函数与赋值函数   如果我们实在不想编写拷贝构造函数和赋值函数,又不允许别人使用编译器生成的缺省函数,怎么办?

C++赋值函数详解

时间: 2024-10-21 15:16:35

C++赋值函数详解的相关文章

c++ 虚函数详解

下面是对C++的虚函数的理解. 一,定义 简单地说,那些被virtual关键字修饰的成员函数,就是虚函数.虚函数的作用,用专业术语来解释就是实现多态性(Polymorphism),多态性是将接口与实现进行分离:用形象的语言来解释就是实现以共同的方法,但因个体差异而采用不同的策略.下面来看一段简单的代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 classA { publi

C++ list容器系列功能函数详解

C++ list函数详解 首先说下eclipse工具下怎样debug:方法:你先要设置好断点,然后以Debug方式启动你的应用程序,不要用run的方式,当程序运行到你的断点位置时就会停住,也会提示你进入到Debug视图方式操作,F5是进入到函数或语句块的内部,F6是单步运行,一行一行的走,F7可以跳当前监听函数或语句块F8 会直接跳到下个断点. 下面进入主题: 一.构造.析构函数.= 运算符 1.功能:声明list容器.4种方式 list<int> first;                

【C语言天天练(二十)】scanf函数详解

引言:scanf函数虽然是学习C语言时比较早就接触的一个函数,但在使用过程中,发现真正掌握它却并不容易.本文就通过各种例子来详细的总结一下该函数的各种用法,假设它的调用格式为 scanf("<格式化字符串>",<地址表>). 1.一般使用scanf函数时都是为某个变量赋值,不考虑它的返回值.但是任何函数都是需要返回的(即使返回类型用void,也可以认为只是调用了return语句,只是并没有返回什么东西而已),同样的scanf函数也是有返回的,它的返回值是成功读取

javascript 函数详解2 -- arguments

今天我们接着上篇文章来继续javascript函数这个主题.今天要讲的是函数对像中一个很重要的属性--arguments. 相关阅读: javascript 函数详解1 -- 概述 javascript 函数详解2 -- arguments Javascript 函数详解3 -- this对象 Javascript 函数详解4 -- 函数的其他属性 Javascript 函数详解5 -- 函数对象的内部函数 arguments对象参数数组引用 arguments是函数对象内部一个比较特殊的类数组

ActiveXObject函数详解(转)

什么是 ActiveX 控件? ActiveX 控件广泛用于 Internet.它们可以通过提供视频.动画内容等来增加浏览的乐趣.不过,这些程序可能出问题或者向您提供不需要的内容.在某些情况下,这些程序可被 用来以您不允许的方式从计算机收集信息.破坏您的计算机上的数据.在未经您同意的情况下在您的计算机上安装软件或者允许他人远程控制您的计算机.考虑到这 些风险,您应该在完全信任发行商的情况下才安装这些程序. 当 Windows 阻止 ActiveX 控件的安装时,您应该做什么? 您可能不应该安装该

jQuery插件开发及jQuery.extend函数详解和jQuery.fn与jQuery.prototype区别

一.jQuery插件开发分为两种:  1.类级别: 类级别你可以理解为拓展jquery类,最明显的例子是$.ajax(...),相当于静态方法. 开发扩展其方法时使用$.extend方法,即jQuery.extend(object); $.extend({ add:function(a,b){return a+b;} , minus:function(a,b){return a-b;} }); var i = $.add(3,2); var j = $.minus(3,2); 2.对象级别: 对

python命名空间与闭包函数详解

python命名空间与闭包函数详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 本篇博客主要介绍的知识点如下: 1>.三元运算 2>.命名空间 3>.global与nonlocal 4>.函数即变量 5>.嵌套函数 6>.闭包函数 一.三元运算 1 #!/usr/bin/env python 2 #_*_coding:utf-8_*_ 3 #@author :yinzhengjie 4 #blog:http://www.cnblogs.com/yi

071:【Django数据库】ORM聚合函数详解-Avg

ORM聚合函数详解-Avg: Avg:求平均值.比如想要获取所有图书的价格平均值.那么可以使用以下代码实现: from django.db.models import Avg result = Book.objects.aggregate(Avg('price')) print(result) 以上的打印结果是: {"price__avg":23.0} 其中price__avg的结构是根据field__avg规则构成的.如果想要修改默认的名字,那么可以将Avg赋值给一个关键字参数.示例

python基础知识~ 函数详解2

python~函数详解2 1 生成器函数   定义 如果函数有yield这个关键字,就是生成器函数.生成器函数() 获取的是生成器,不执行函数  须知 yield和return一样,都可以返回数据,但是不会彻底中断函数,分段进行函数处理  继续执行 函数(迭代器)  __next__()   __send__(参数)//和next具有同一个功能,还添加了给上一个值赋值功能  def func()  print(a)  a=yield 1 //yield特殊定义   print (b)  b=yi