分享

这样的运算符重载总结,太爱了!

 zeroxer2008 2022-01-13
大家好,我是行码棋。今天跟大家介绍c++的运算符总结的知识,在平常c++代码的使用中,经常会用到这样的知识点,还是有必要进行学习的。废话不多说,开始干正事!

图片

1.运算符new,delete介绍

1.1.new申请空间

形式:

指针变量 = new<数据类型>[长度]

  • 申请一个整型(int)空间
int *ptr;
ptr = new int;
  • 申请一个整型空间并且初始化
int *ptr;
ptr = new int(5);
  • 申请长度为20的一维数组,但不能进行初始化
int *p;
p = new int[10];

「注意:」

  • 当分配的长度为1个单位时,可以省略方括号里面的整数。
int *int_ptr = new int;
//等价形式
int *int_p = new int[1];
  • 使用new分配空间时,方括号里面的数值可以是常量,也可以是变量。还可以是数值表达式。
int size = 10;
//常量
int *np = new int[5];
//变量
int *np1 = new int[size];
//表达式
int *np2 = new int[size+10];
  • 使用new分配的空间是连续的,可以使用指针访问分配空间里面的每一个元素。
int *p = new int[20];

//将第11个元素赋值为100
p[10] = 100;
//或者
*(p+10) = 100;
  • 如果当前存储器无法分配更多的内存空间,new运算符返回值为0(NULL)

1.2.delete释放空间

delete释放空间只有两种形式:

//1
delete p;
//2
delete []p;

delete: 释放new分配的单个对象指针指向的内存

delete[]:  释放new分配的对象数组指针指向的内存

其实两种方式区别不大,主要区分在类中体现。

1.针对简单类型(int,float,long,double,char,struct等)

使用new分配后的无论是数组还是非数组形式内存空间「用两种方式均可」

如:

 int *a = new int[10];
 delete a;
 //或delete [] a; 

此种情况中的释放效果相同 原因在于分配简单类型内存时,内存大小已经确定,系统可以记忆并且进行管理,在析构时,系统并不会调用析构函数,

2.对于类class来说,两种方式体现出差异。

A *a = new A[10];
delete a;
//仅释放了a指针指向的全部内存空间 但是只调用了a[0]对象的析构函数 剩下的从a[1]到a[9]这9个用户对应内存空间将不能释放从而造成内存泄漏
delete [] a;
//释放了a指针指向的全部内存空间 并且调用使用类对象的析构函数释放用户自己分配的内存空间

注意:

①用new运算符获得的内存空间,只许使用一次delete,不允许多次对同一块空间进行多次释放,否则将会产生严重错误。

②delete只能用来释放由new运算符分配的动态内存空间,对于程序中的变量、数组的存储空间,不得使用delete运算符去释放。

2.运算符重载

运算符重载是通过定义函数实现的,即定义一个重载运算符的函数,在需要执行被重载的运算符时,系统自动调用该函数,以实现相应的运算。

「运算符重载实质上是函数的重载。」

「重载形式」

函数类型 operator 运算符名称 (形参表列)  { 对运算符的重载处理 }

2.1.相关问题

  • 运算符能否进行重载

「可以重载的运算符」

+   -   *   /   %   ^   &   |   ~ !   =   <   >   +=   -=   =   /=   % ^=   &=   |=   <<   >>   >>=   <<=   ==   != <=   >=   &&   ||   ++   --   ->   '   -> []   ()   new   delete   new[]   delete[]

「不能重载的运算符」

「Operator」「Name」
「.」「类属关系运算符」
「.*」「成员指针运算符」
「::」「作用域运算符」
「? :」「条件运算符」
「#」「编译预处理符号」
「sizeof()」「取数据类型的长度」
  • 运算符重载不能创造新的运算符号,例如不能创建@@表示幂运算
  • 重载的运算符保持运算符的一些性质不变(优先级,结合性,操作个数,语法结构)
  • 赋值运算符(=)和地址运算符(&)不需要重载

「运算符重载函数一般采用两种方式:」

  • 成员函数的形式
  • 友元函数的形式

运算符函数是一种特殊的成员函数或友员函数(全局函数通常被指定为友元函数)

2.2.常见运算符重载示例

+,- 运算符,以复数的运算为例:

#include<bits/stdc++.h>
using namespace std;

class Complex
{

private:
    double real,imag;//实部和虚部
public:
    Complex(double r=0,double i=0):real(i),imag(i){}//构造函数
    Complex operator +(const Complex &a);//重载+运算符
    Complex operator -(const Complex &a);//重载-运算符
    void print();
};
//定义为成员函数,可以访问类内的私有变量
Complex Complex::operator +(const Complex&a)
{
    Complex temp(real+a.real,imag+a.imag);
    return temp;
}
Complex Complex::operator -(const Complex&a)
{
    Complex temp(real-a.real,imag-a.imag);
    return temp;
}
void Complex::print()
{
    cout<<real<<' ';
    if(imag!=0)
    {
        if(imag>0cout<<'+ ';
        cout<<imag<<'i\n';
    }
}
int main()
{
 Complex t1(1,2);
    Complex t2(2,3);
    t2 = t1 + t2;//对象的赋值
    t2.print();
 return 0;
}

++ ,--重载

#include<bits/stdc++.h>
using namespace std;

class number
{

private:
    int num;
public:
    number(int n=0):num(n){};
    number& operator++();//前置自增
    number operator++(int);//后置自增
    void print();
};
number& number::operator++()
{
    num++;
    return *this;//前置自增要保证先增加,然后返回增加后的数据,所以返回类型是引用类型
}
number number::operator++(int)//int为形式参数,不参与实际运算
{
    number temp(*this);//保存临时的变量
    num++;//自增1
    return temp;//返回之前保存的没有进行加自增的变量
}
void number::print()
{
    cout<<num<<endl;
}
int main()
{
    number n1(2);
    n1++;
    n1.print();
    ++n1;
    n1.print();
    return 0;
}

1、运算符「前置」自增运算符 , 用成员函数实现时,「没有」形式参数。

2、运算符「后置」自增运算符 ,另外「增加」一个形式上的「形式参数」,类型定为int。

这个参数只是用来区别两种自增算符,并不参加实际的运算。

<< 和>>运算符重载

#include<iostream>
using namespace std;
class Complex
{

private:
    double real,imag;
public:
    Complex(double r=0,double i=0):real(r),imag(i){}
    friend istream& operator >> (istream& in,Complex &c);
    friend ostream& operator << (ostream& out,Complex c);
};
istream& operator >> (istream& in,Complex &c)
{
    cout<<'请输入实部和虚部\n';
    in >> c.real >> c.imag;
    return in;
}
ostream& operator << (ostream& out,Complex c)
{
    if(c.real!=0)
    {
        out << c.real ;//实部输出
        if(c.imag==0)
        {
            out << 0 << '\n';
            return out;
        }
        else if(c.imag>0)
        {
            out << '+' << c.imag <<'i\n';
            return out;
        }
        else 
        {
            out << c.imag << 'i\n';
            return out;
        }
    }
}
int main()
{
 Complex cc;
    cin>>cc;
    cout<<cc;
 return 0;
}

3.类型转换函数(类型转换运算符)

格式:

operator type(){
    //具体代码
    return data;
}
  • type 是要转换的目标类型,data 是要返回的 type 类型的数据。

  • 返回值data的类型和type目标类型必须是一样的。既然已经知道了要返回 type 类型的数据,所以没有必要再像普通函数一样明确地给出返回值类型。

  • 类型转换函数看起来没有返回值类型,其实是隐式地指明了返回值类型。

  • 类型转换函数也没有参数,因为要将当前类的对象转换为其它类型,所以参数不言而喻。

#include <iostream>
using namespace std;

class Complex
{

public:
    Complex(): real(0.0), imag(0.0){ }
    Complex(double real, double imag): real(real), imag(imag){ }
public:
    friend ostream & operator<<(ostream &out, Complex &c);
    //实现两个复数的相加
    friend Complex operator+(const Complex &c1, const Complex &c2);
    
    operator double() const return real; }  //类型转换函数
private:
    double real;  //实部
    double imag;  //虚部
};

//重载>>运算符
ostream & operator<<(ostream &out, Complex &c)
{
    out << c.real <<' + '<< c.imag <<'i';;
    return out;
}
//重载+运算符
Complex operator+(const Complex &c1, const Complex &c2)
{
    Complex c;
    c.real = c1.real + c2.real;
    c.imag = c1.imag + c2.imag;
    return c;
}

int main()
{
    Complex c1(24.6100);
    double f = c1;  //相当于 double f = Complex::operator double(&c1);
    cout<<'f = '<<f<<endl;
 
    f = 12.5 + c1 + 6;  //相当于 f = 12.5 + Complex::operator double(&c1) + 6;
    cout<<'f = '<<f<<endl;
 
    int n = Complex(43.29.3);  //先转换为 double,再转换为 int
    cout<<'n = '<<n<<endl;

    return 0;
}

运行结果:

f = 24.6
f = 43.1
n = 43

「注意:」

  1. type 可以是内置类型、类类型以及由 typedef 定义的类型别名,任何可作为函数返回类型的类型(void 除外)都能够被支持。一般而言,不允许转换为数组或函数类型,转换为指针类型或引用类型是可以的。

  2. 类型转换函数一般不会更改被转换的对象,所以通常被定义为 const 成员。

  3. 类型转换函数可以被继承,可以是虚函数。

  4. 一个类虽然可以有多个类型转换函数(类似于函数重载),但是如果多个类型转换函数要转换的目标类型本身又可以相互转换(类型相近),那有时候就会产生二义性。例如:

operator double() const return m_real; }  //转换为double类型
operator int() const return (int)m_real; }  //转换为int类型

那么下面的代码就会出错:

Complex c(12.230);
float f = 1.1 + c;

编译器「可以」调用 operator double() 将 c 转换为 double 类型,「也可以」调用 operator int() 将 c 转换为 int 类型,两种数据类型都可以和 1.1 进行加法运算。而且从 Complex 转换为 double 与从 Complex 转化为 int 是同级关系,没有谁的优先级是更高的。

以上内容即为全部的内容,如果对你有帮助,欢迎点赞关注哦~

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多