为数偶类定义专用的赋值操作符

  1. class Couple
  2. {
  3. public:
  4. Couple(int a = , int b = ) :_a(a), _b(b) {}
  5. Couple(const Couple &c):_a(c._a),_b(c._b){}
  6. Couple &operator=(const Couple &c);
  7. private:
  8. int _a, _b;
  9. };
  10.  
  11. Couple & Couple::operator=(const Couple &c)
  12. {
  13. if (*this == c)//在不同的情况下,此语句可能会降低程序的执行的效率,比如多数情况下赋值的不是对象自身,因此要根据情况判定;
  14. {
  15. return *this;
  16. }
  17. _a = c._a;
  18. _b = c._b;
  19. return *this;
  20. }
  21.  
  22. int main()
  23. {
  24. Couple a(, ), b(, );
  25. cout << a << endl;
  26. a = b;
  27. cout << a << endl;
  28. return ;
  29. }

为数偶类定义专用的简写四则运算符

  1. class Couple
  2. {
  3. public:
  4. Couple(int a = , int b = ) :_a(a), _b(b) {}
  5. Couple(const Couple &c) :_a(c._a), _b(c._b) {}
  6. Couple &operator+=(const Couple &c);
  7. Couple &operator*=(const Couple &c);
  8. Couple &operator*=(const int &k);
  9. private:
  10. int _a, _b;
  11. };
  12.  
  13. Couple & Couple::operator+=(const Couple &c)
  14. {
  15. _a += c._a;
  16. _b += c._b;
  17. return *this;
  18. }
  19.  
  20. Couple & Couple::operator*=(const Couple &c)
  21. {
  22. _a *= c._a;
  23. _b *= c._b;
  24. return *this;
  25. }
  26.  
  27. Couple & Couple::operator*=(const int &k)
  28. {
  29. _a *= k;
  30. _b *= k;
  31. return *this;
  32. }

为数偶类定义专用的递增递减操作符

  1. class Couple
  2. {
  3. public:
  4. Couple(int a = , int b = ) :_a(a), _b(b) {}
  5. Couple(const Couple &c) :_a(c._a), _b(c._b) {}
  6. Couple & operator=(const Couple &c);
  7. Couple & operator++();//前缀递增,返回本对象的引用
  8. Couple operator++(int);//后缀递增,返回本对象的拷贝
  9. private:
  10. int _a, _b;
  11. };
  12.  
  13. Couple & Couple::operator++()
  14. {
  15. ++_a, ++_b;
  16. return *this;
  17. }
  18.  
  19. Couple Couple::operator++(int _t)
  20. {
  21. Couple _t(*this);
  22. _a++, _b++;
  23. return _t;
  24. }

赋值操作符的返回值

  • 除后缀递增递减操作符,应返回对象的引用,以与C++本身的语义相符合
  • 返回对象需要额外的对象构造,降低效率
  • 如果不需要返回值以进行连续赋值,可以将返回值设为void,但要注意此时重载的操作符语义与C++不符合,故不推荐

赋值构造与拷贝构造

赋值也是构造

拷贝、赋值与析构三位一体,一般同时出现

  • 缺省赋值构造与拷贝构造为浅拷贝
  • 如果对象没有指针成员,缺省行为即可满足要求,无需实现或重载这三个函数
  • 如果对象有指针成员,一般需要重载这三个函数

浅拷贝

  1. class A
  2. {
  3. public:
  4. A():_n(),_p(NULL){}
  5. explicit A(int n) :_n(n), _p(new int[n]) {}//把数组的基地址赋值给_p
  6. A(int n, int *p) :_n(n), _p(p) {}
  7. //如果省略以下语句,编译器自动生成以下两条语句(浅拷贝)
  8. A(const A & that) :_n(that._n), _p(that._p) {}//浅拷贝
  9. A & operator=(const A & that) { _n = that._n, _p = that._p; return *this; }
  10. virtual ~A() { if (_p) { delete[]_p; _p = NULL; } }
  11. public:
  12. int & operator[](int i);
  13. const int & operator[](int i) const;
  14. private:
  15. int _n;
  16. int *_p;
  17. };
  18.  
  19. int & A::operator[](int i)
  20. {
  21. if (i < || i >= )
  22. throw std::out_of_range("Out of range when trying to access the object... ");
  23. return _p[i];
  24. }
  25.  
  26. const int & A::operator[](int i) const
  27. {
  28. if (i < || i >= )
  29. throw std::out_of_range("Out of range when trying to access the object..");
  30. return _p[i];
  31. }
  32.  
  33. int main()
  34. {
  35. A a(), b;
  36. for ( int i = ; i < ; i++)
  37. {
  38. a[i] = i + ;
  39. }
  40. std::cout << "Before object assignment:" << std::endl;
  41. for (int i = ; i < ; i++)
  42. {
  43. std::cout << a[i] << " ";
  44. }
  45. std::cout << std::endl;
  46. b = a;
  47. std::cout << "After object assignment:" << std::endl;
  48. for (int i = ; i < ; i++)
  49. {
  50. std::cout << b[i] << " ";
  51. }
  52. std::cout << std::endl;
  53. return ;//程序结束时,系统崩溃
  54. }

对象a是main函数中定义的局部变量,当程序结束时对象a的_p会释放其指向的目标存储区,而对象b同样会去销毁目标存储区,但是目标存储区已被释放,此时出现了空悬指针;导致b在销毁对象使用delete[]时,程序崩溃;

解决方法:

  • 使用深拷贝(拷贝一份指针指向目标数据对象的副本)

  1. class A
  2. {
  3. public:
  4. A():_n(),_p(NULL){}
  5. explicit A(int n) :_n(n), _p(new int[n]) {}//把数组的基地址赋值给_p
  6. A(int n, int *p) :_n(n), _p(p) {}
  7. A(const A & that);
  8. A & operator=(const A & that);
  9. virtual ~A() { if (_p) { delete[]_p; _p = NULL; } }
  10. public:
  11. int & operator[](int i);
  12. const int & operator[](int i) const;
  13. private:
  14. int _n;
  15. int *_p;
  16. };
  17.  
  18. A::A(const A & that)//拷贝构造函数
  19. {
  20. this->_n = that._n;
  21. _p = new int[_n];
  22. for (int i = ; i < _n; i++)
  23. {
  24. _p[i] = that._p[i];
  25. }
  26. }
  27.  
  28. A & A::operator=(const A & that)//重载赋值运算符
  29. {
  30. this->_n = that._n;
  31. if (_p)
  32. {
  33. delete[]_p;
  34. }
  35. _p = new int[_n];
  36. for (int i = ; i < _n; i++)
  37. {
  38. _p[i] = that._p[i];
  39. }
  40. return *this;
  41. }

注意:在赋值操作时本对象其实已经存在,_P可能指向一个有意义的数组,数组在赋值操作后即失去意义,所以要先删除_p指向的目标数组,然后对它进行创建连续的存储区,一个一个元素地拷贝;

C++学习笔记12:运算符重载(赋值操作符1)的更多相关文章

  1. C++学习笔记之运算符重载

    一.运算符重载基本知识 在前面的一篇博文 C++学习笔记之模板(1)——从函数重载到函数模板 中,介绍了函数重载的概念,定义及用法,函数重载(也被称之为函数多态)就是使用户能够定义多个名称相同但特征标 ...

  2. C++基础 学习笔记五:重载之运算符重载

    C++基础 学习笔记五:重载之运算符重载 什么是运算符重载 用同一个运算符完成不同的功能即同一个运算符可以有不同的功能的方法叫做运算符重载.运算符重载是静态多态性的体现. 运算符重载的规则 重载公式 ...

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

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

  4. matlab学习笔记12单元数组和元胞数组 cell,celldisp,iscell,isa,deal,cellfun,num2cell,size

    一起来学matlab-matlab学习笔记12 12_1 单元数组和元胞数组 cell array --cell,celldisp,iscell,isa,deal,cellfun,num2cell,s ...

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

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

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

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

  7. Ext.Net学习笔记12:Ext.Net GridPanel Filter用法

    Ext.Net学习笔记12:Ext.Net GridPanel Filter用法 Ext.Net GridPanel的用法在上一篇中已经介绍过,这篇笔记讲介绍Filter的用法. Filter是用来过 ...

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

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

  9. SQL反模式学习笔记12 存储图片或其他多媒体大文件

    目标:存储图片或其他多媒体大文件 反模式:图片存储在数据库外的文件系统中,数据库表中存储文件的对应的路径和名称. 缺点:     1.文件不支持Delete操作.使用SQL语句删除一条记录时,对应的文 ...

  10. golang学习笔记12 beego table name `xxx` repeat register, must be unique 错误问题

    golang学习笔记12 beego table name `xxx` repeat register, must be unique 错误问题 今天测试了重新建一个项目生成新的表,然后复制到旧的项目 ...

随机推荐

  1. 转载:Clear Float

    众所周知,平时在写HTML代码时,难免少不了使用Float样式,这样一来,假使您没有清除浮动,那么有浮动元素的父元素容器将元素将无法自动撑 开.换句简单好理解的话来说,假如你在写CODE时,其中div ...

  2. Objective-C(面向对象的三大特性)

    封装 set方法 作用:提供一个方法给外界设置成员变量值,可以在方法里面进行过滤 命名规范 1. 方法名必须以set开头 2. set后面跟上成员变量的名称,成员变量的首字母必须大写 3. 返回值一定 ...

  3. cmd扩展路径

    在命令行窗口中,输入for /? 即可得到如下参数解释==== 对一组文件中的每一个文件执行某个特定命令. FOR %variable IN (set) DO command [command-par ...

  4. SQL语句大全(mysql,sqlserver,oracle)

    SQL语句大全 --语句功能--数据操作SELECT --从数据库表中检索数据行和列-selectINSERT --向数据库表添加新数据行-insertDELETE --从数据库表中删除数据行-del ...

  5. 关于linux服务器的批量维护、批量升级、

    由于版权费用原因,众多中小服务器采用linux服务器进行功能处理.在进行批量升级.更新业务程序时.可以采用如下批量方案: 1.打包成rpm包,并配置yum源服务器,以支持个人的yum服务器进行处理.一 ...

  6. [css3]搜索框focus时变长

    结构: <form class="demo-a">    <input placeholder="Search" type="sea ...

  7. 解决visualsvn监听ip 错误的问题

    系统重启+休眠之类的,弄几次,莫名其妙的svn就连接不上了, 有时候启动不起,有时候是启动连接不上,发现监听的ip错了 TCP    [::]:443               [::]:0     ...

  8. zabbix3.0部署(LAMP)

    0.1 初始化 #!/bin/sh yum clean all systemctl stop firewalld.service systemctl disable firewalld.service ...

  9. 【NOIP2015】提高组D1 解题报告

    P1978神奇的幻方 Accepted 描述 幻方是一种很神奇的 N ∗ N 矩阵:它由数字 1,2,3, … … , N ∗ N 构成,且每行.每列及两条对角线上的数字之和都相同. 当 N 为奇数时 ...

  10. Android 插入图片到媒体库

    今天介绍一下在Android中怎么插入图片到媒体库,下面看代码: final String titleName = Function.md5(imageUri.toLowerCase()) + &qu ...