1、C++中重载赋值操作函数应该返回什么?

  类重载赋值操作符一般都是作为成员函数而存在的,那函数应该返回什么类型呢?参考内置类型的赋值操作,例如

  int x,y,z;

  x=y=z=15;

  赋值行为相当于x=(y=(z=15)),也就是赋值操作应该返回左操作数的引用,因此,为了和内置类型兼容,类中重载赋值操作符应该返回左操作数的引用,即*this,如下类A的重载赋值操作函数的声明,

  class A{};

  A& A::operator=(const A&);

2、确保重载赋值操作具有良好的行为

  对于赋值操作,首先应该想到的是怎么处理自我赋值,当类包含指针类型的数据时尤为重要,如下所示

  class MyString{

    public:

      ...

      MyString(char *p=NULL);

      MyString& operator=(const MyString&);

    private:

      char *str;

  };

  MyString a("hello");

  MyString b("world");

  a=a;

  我们知道,进行赋值时,首先要释放左操作数的资源,然后再根据右操作数对左操作数进行赋值,赋值操作函数如下所示

  MyString& MyString::operator=(const MyString& rhs){

    delete [] str;

    str=new char[strlen(rhs.str)+1];

    strcpy(str,rhs.str);

    return *this;

  }

  当运行a=a时,会产生意向不到的后果,我们在函数中先释放了左操作数的资源,然后访问右操作数的资源,然后当自我赋值发生时,this==&rhs,也就是说我们先释放了资源,然后又访问了已经被释放的资源的内容,这显然会引起程序崩溃,所以我们需要进行是否是自我赋值操作的验证,修改过后的函数如下

  MyString& MyString::operator=(const MyString& rhs){

    if(this==&rhs)

      return *this;

    delete [] str;

    str=new char[strlen(rhs.str)+1];

    strcpy(str,rhs.str);

    return *this;

  }

  此时,函数虽然处理了自我赋值,但是仍然存在问题,如果new操作失败了怎么办?

  我们已经释放了左操作数的资源,但是在重新分配资源时由于空间不够等原因失败了,如果我们继续对已经释放了的资源进行访问,会产生未定义的结果,赋值操作就不具备异常安全性,对于这个问题有两种解决方案

  第一,调整语句顺序,先保存原来的资源,等重新分配资源完成以后再释放以前的资源

  MyString& MyString::operator=(const MyString& rhs){

    char *pTemp=str;

    str=new char[strlen(rhs.str)+1];

    strcpy(str,rhs.str);

    delete [] pTemp;

    return *this;

  }

  这段代码也能够处理自我赋值,但是必须执行完函数中的所有复制、分配和释放操作,如果自我赋值发生的概率比较高,我们也可以将测同语句放进该函数。

  第二、采用copy and swap技术

  MyString& MyString::operator=(const MyString& rhs){

    if(this!=&rhs){

      MyString temp(rhs);

      char *pTemp=str;

      str=temp.str;

      temp.str=pTemp;

    }

    return *this;

  }

  这种技术赋值的是指针而不是为对象重新分配资源,我们在if语句内重新构造了一个新的临时对象,然后将临时对象的str和本类对象的str进行交换,当程序执行到if语句外时,临时对象自动调用析构函数,释放自己的资源,此时临时对象所持有的资源就是原来this所持有的资源,该资源得以释放,而现在this所持有的资源是rhs所持有的资源,即此时rhs和this中的str所指向的是同一块空间。

3、复制对象时切勿忘记复制其每一个元素

  对于有继承关系的类,在对其派生类编写复制控制的函数时,由于派生类无法访问基类中的私有成员,所以在派生类的重载操作符函数中,需要首先调用其基类的赋值操作符函数对派生类中的基类成员进行赋值,然后再对派生类中的特有成员进行赋值。

C++重载赋值操作符的更多相关文章

  1. C++ 之 重载赋值操作符

    Widget 类中,定义了一个 Bitmap 类型的私有数据成员 -- pb 指针 class Bitmap { ... }; class Widget { private: Bitmap *pb; ...

  2. C++中复制构造函数与重载赋值操作符总结

    前言 这篇文章将对C++中复制构造函数和重载赋值操作符进行总结,包括以下内容: 1.复制构造函数和重载赋值操作符的定义: 2.复制构造函数和重载赋值操作符的调用时机: 3.复制构造函数和重载赋值操作符 ...

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

    我们都知道,在C++中建立一个类,这个类中肯定会包括构造函数.析构函数.复制构造函数和重载赋值操作:即使在你没有明确定义的情况下,编译器也会给你生成这样的四个函数.例如以下类:   class CTe ...

  4. 5.5 C++重载赋值操作符

    参考:http://www.weixueyuan.net/view/6383.html 总结: 重载赋值操作符同重载类的是拷贝构造函数的原因是一样,将一个对象拷贝给另一个对象,同时当类中存在指针类型的 ...

  5. Effective C++(10) 重载赋值操作符时,返回该对象的引用(retrun *this)

    问题聚焦: 这个准则比较简短,但是往往就是这种细节的地方,可以提高你的代码质量. 细节决定成败,让我们一起学习这条重载赋值操作符时需要遵守的准则吧. 还是以一个例子开始: Demo // 连锁赋值 x ...

  6. C++ 数组操作符重载、函数对象分析、赋值操作符

    string类型访问单个字符 #include <iostream> #include <string> #include <sstream> using name ...

  7. C++中的赋值操作符重载和拷贝构造函数

    1,关于赋值的疑问: 1,什么时候需要重载赋值操作符? 2,编译器是否提供默认的赋值操作符? 2,关于赋值的疑问: 1,编译器为每个类默认重载了赋值操作符: 1,意味着同类型的类对象可以相互赋值: 2 ...

  8. 【c++】c++中重载输出操作符,为什么要返回引用

    针对:ostream & operator <<(ostream & os, const ClassType &object) 说明几点: 1.第一个形参为对ost ...

  9. [C++]复制构造函数、赋值操作符与隐式类类型转换

    问题:现有类A定义如下: class A{public:        A(int a)                            //构造函数        {              ...

随机推荐

  1. PHP语言开发微信公众平台(订阅号)之注册(1)

    1.百度搜索"微信公众平台" 2.选择微信公众平台官网并单击打开 3.进入官网页面,单击 "立即注册" 进入注册页面 4.进入注册页面,单击订阅号 5.进入订阅 ...

  2. PHP设计模式——装饰器模式

    <?php /** * 装饰器模式 * 如果已有对象的部分内容或功能发生变化,但是不需要修改原始对象的结构,应使用装饰器模式 * * 为了在不修改对象结构的前提下对现有对象的内容或功能稍加修改, ...

  3. centos7 编译安装nginx1.16.0( 完整版 )

    一.安装依赖包 yum install -y gcc gcc-c++ pcre pcre-devel zlib zlib-devel openssl openssl-devel 依赖包说明: 1.编译 ...

  4. 八、IntelliJ IDEA 缓存和索引的介绍及清理方法

    这样一句话“ 对于首次创建或打开的新项目,IntelliJ IDEA 都会创建项目索引,大型项目在创建索引的过程中可能会出现卡顿的现象,因此强烈建议在 IntelliJ IDEA 创建索引的过程中不要 ...

  5. java递归菜单树转换成pojo对象

    package com.cjonline.foundation.authority.pojo; import java.util.ArrayList; import java.util.Collect ...

  6. C# 动态改变webservice的访问地址

    1.添加一个App.config配置文件. 2.配置服务http://Lenovo-PC:80/EvisaWS/WharfService?wsdl,那么在上面的文件中就会自动生成服务的配置: < ...

  7. LeetCode7.整数反转 JavaScript

    给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转. 示例 1: 输入: 123 输出: 321 示例 2: 输入: -123 输出: -321 示例 3: 输入: 120 输出: ...

  8. CSS 中定位方式有几种,说明他们的意义

    1.static  默认定位方式 显示为没有设置定位时的位置 2.fixed(固定定位)  他所相对固定的对象是可视窗口,与其他无关.以浏览器窗口作为参考进行定位 3.relative(相对定位) 元 ...

  9. 复制D:\\day05目录下的所有文件到D:\\copy,并将.txt文件改为.java文件。

    **解题思路: 1.首先定义一个静态的refile方法,参数传入两个文件路径 2.要复制目录下的所有文件,首先查询File类的方法,可以使用listFiles方法得到目录下的文件 3.想到这问题基本就 ...

  10. 设置全局导航栏颜色,标题大小和UIBarButtonItem字体大小

    设置全局导航栏颜色,标题大小和UIBarButtonItem字体大小 在appdelegate里面设置 swift: UINavigationBar.appearance().barTintColor ...