【C++】运算符重载/函数的返回值为解引用

运算符重载:

原因:为了增强程序的可读性,引入运算符重载。目的就是为了让自定义的类型能够像内置类型一样可以直接使用运算符计算。换可以使用C++中的运算符操作对象。

语法:返回值类型 operator 运算符 (形参列表)

1.1 = 运算符重载

当使用一个已存在的对象,给另外一个已存在的对象赋值的时候自动调动的成员方法。
如果没有实现,会自动生成一个浅拷贝的等号运算符重载。

person &operator=(const person& src)
    {
        //防止自赋值
        if (this !=&src)
        {
        //防止内存泄漏
        delete[] _name;//将被赋值的_name中的内存释放,重新申请。
        //防止浅拷贝
        _name = new char(strlen(src._name) + 1);
        memset(_name, 0, strlen(src._name)+1);
        for (int i = 0; i < strlen(src._name); i++)
        {
            _name[i] = src._name[i];
        }
        _sex = src._sex;
        _age = src._age;
        }
        return *this;
        //打印一些说明调用了此函数
        cout << "void operator=(const person &src)" << endl;
    }
int main(void)
{
    char name[] = "baiU";
    person p1(name,1, 22);
    person p2;
    p2 = p1;
    //等同于:p2.operator=(p1);
    p2.show();
    return 0}

运行结果
请添加图片描述
结果显示
首先构造p1,接下来构造p2,在调用赋值运算符重载。析构p2,在析构p1。
注意
1.防止自赋值
2.防止内存泄漏
3.防止浅拷贝
如果成员属性中有指针。就绪要额外申请空间。防止浅拷贝。

1.2 + 运算符重载

  1. 返回类型为类的类型
  2. this指针声明为const
  3. 第二加数声明为const
 Complex operator+(const Complex &cx)const
Complex operator+(const Complex &cx)const
    {
        //int a = Real + cx.Real;
        //int b = Image+cx.Image;
        //调用了拷贝构造函数,将this和cx的和传给tmp
        Complex tmp(Real + cx.Real,Image+cx.Image);
        
        //return   Complex(Real + cx.Real,Image+cx.Image); //不需要调用拷贝构造函数,直接创建一个临时对象,将值写入到临时对象空间
        return tmp; //创建了一个临时对象,只析构一次
    }
  Complex p1(5, 6);
  Complex p2(7, 8);
  Complex p3 = p1 + p2;
 // Complex p4 = p1.operator+(p2);

请添加图片描述

1.3 && 运算符

比如要比较两个复数的实部是否等于0

bool operator &&(const Complex& cx)const
    {
        return Real && cx.Real;
    }
    

1.4 << 运算符(输出运算符)

把cout当做cout当做参数穿进去
使用特定的 ostream
//简易版本,只能当做show方法一样使用

   /* void operator<<(ostream& out)
    {
        out << Real << "+" << Image << "i" << endl;
    }
    */

请添加图片描述
无法使用cout直接输出

改进:将函数的返回值类型改为输出流对象,即ostream

 friend ostream& operator<<(ostream& out, const Complex& cx);
};
ostream &operator<<(ostream& out, const Complex& cx)
{
    out << cx.Real << "+" << cx.Image << "i" << endl;
    return out;
}

一次输出两个对象

 cout << p1<<p2 ;

请添加图片描述

1.5 ++运算符

前置 ++(仅对实部++)

前置++就是先+1,再返回
实现:只针对复数的实部

  1. 引用的方式返回函数的值,不能是局部变量,或局部对象
  2. 返回的是this指针的本身。
    用引用作函数的返回值的最大的好处是在内存中不产生返回值的副本。
Complex& operator++()
    {
       ++Real;
       return *this;
     }

后置++(仅对实部++)

先传值,再自增。
就是先把值给一个临时量。

 Complex operator++(int)
    {
        int tmp = Real;
        ++Real;
        return Complex(tmp,Image);
    }

函数的返回值为解引用?

  1. 当函数运算符重载返回的是对象时,会在连续赋值运算过程中,调用两次拷贝构造函数和析构函数,(return 创建一个新对象),而如果采用 引用的方式返回,就不需要在创建对象,因为return的就是已经存在的对象的引用(别名)。
  2. 用引用作函数的返回值的最大的好处是在内存中不产生返回值的副本
  3. 允许连续赋值
#include<iostream>
#include<string.h>
using namespace std;
class String
{
private:
    char* str;
    int len;
public:
    String(const char* s);//构造函数声明
    String &operator=(const String& another);//运算符重载,此时返回的是对象
    void show()
    {
        cout << "value = " << str << endl;
    }

    /*copy construct*/
    String(const String& other)
    {
        len = other.len;
        str = new char[len + 1];
        strcpy_s(str, len+1,other.str);
        cout << "copy construct" << endl;
    }

    ~String()
    {
        delete[] str;
        cout << "deconstruct" << endl;
    }
};

String::String(const char* s)//构造函数定义
{
    len = strlen(s);
    str = new char[len + 1];
    strcpy_s(str,len+1, s);
}

String String::operator=(const String& other)//运算符重载
{
    if (this == &other)
        return *this;
    //        return;
    delete[] str;
    len = other.len;
    str = new char[len + 1];
    strcpy_s(str,len+1, other.str);
    return *this;
    //    return;
}

int main()
{
    String str1("abc");
    String str2("123");
    String str3("456");
    str3 = str1 = str2;//str3.operator=(str1.operator=(str2))
    str3.show();
    str1.show();
    return 0;
}

请添加图片描述

如果以解引用的方式返回

String &String::operator=(const String& other)//运算符重载
{
    if (this == &other)
        return *this;
    //        return;
    delete[] str;
    len = other.len;
    str = new char[len + 1];
    strcpy_s(str,len+1, other.str);
    return *this;
    //    return;
}

请添加图片描述

  str3 = str1 = str2;//str3.operator=(str1.operator=(str2))

少执行了两次拷贝构造函数,因为返回的都是this的别名,因此是对str进行了修改买就可以完成连续赋值。

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
目 录 前 言 6 第1章 文件结构 11 1.1 版权和版本的声明 11 1.2 头文件的结构 12 1.3 定义文件的结构 13 1.4 头文件的作用 13 1.5 目录结构 14 第2章 程序的版式 15 2.1 空行 15 2.2 代码行 16 2.3 代码行内的空格 17 2.4 对齐 18 2.5 长行拆分 19 2.6 修饰符的位置 19 2.7 注释 20 2.8 类的版式 21 第3章 命名规则 22 3.1 共性规则 22 3.2 简单的WINDOWS应用程序命名规则 23 3.3 简单的UNIX应用程序命名规则 25 第4章 表达式和基本语句 26 4.1 运算符的优先级 26 4.2 复合表达式 27 4.3 IF 语句 27 4.4 循环语句的效率 29 4.5 FOR 语句的循环控制变量 30 4.6 SWITCH语句 30 4.7 GOTO语句 31 第5章 常量 33 5.1 为什么需要常量 33 5.2 CONST 与 #DEFINE的比较 33 5.3 常量定义规则 33 5.4 类中的常量 34 第6章 函数设计 36 6.1 参数的规则 36 6.2 返回值的规则 37 6.3 函数内部实现的规则 39 6.4 其它建议 40 6.5 使用断言 41 6.6 引用与指针的比较 42 第7章 内存管理 44 7.1内存分配方式 44 7.2常见的内存错误及其对策 44 7.3指针与数组的对比 45 7.4指针参数是如何传递内存的? 47 7.5 FREE和DELETE把指针怎么啦? 50 7.6 动态内存会被自动释放吗? 50 7.7 杜绝“野指针” 51 7.8 有了MALLOC/FREE为什么还要NEW/DELETE ? 52 7.9 内存耗尽怎么办? 53 7.10 MALLOC/FREE 的使用要点 54 7.11 NEW/DELETE 的使用要点 55 7.12 一些心得体会 56 第8章 C++函数的高级特性 57 8.1 函数重载的概念 57 8.2 成员函数重载、覆盖与隐藏 60 8.3 参数的缺省值 63 8.4 运算符重载 64 8.5 函数内联 65 8.6 一些心得体会 68 第9章 类的构造函数、析构函数与赋值函数 69 9.1 构造函数与析构函数的起源 69 9.2 构造函数的初始化表 70 9.3 构造和析构的次序 72 9.4 示例:类STRING的构造函数与析构函数 72 9.5 不要轻视拷贝构造函数与赋值函数 73 9.6 示例:类STRING的拷贝构造函数与赋值函数 73 9.7 偷懒的办法处理拷贝构造函数与赋值函数 75 9.8 如何在派生类中实现类的基本函数 75 9.9 一些心得体会 77 第10章 类的继承与组合 78 10.1 继承 78 10.2 组合 80 第11章 其它编程经验 82 11.1 使用CONST提高函数的健壮性 82 11.2 提高程序的效率 84 11.3 一些有益的建议 85 参考文献 87 附录A :C++/C代码审查表 88 附录B :C++/C试题 93 附录C :C++/C试题的答案与评分标准 97

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值