C++学习笔记(二) 运算符重载

操作符重载

定义:让加减乘除,不局限于整型数的操作,也可以实现类的相加…

实例:

加法重载
class Point
{
    
    
   private:
     int x;
     int y;
   ...
};

Point operator+(Point &p1, Point &p2)
{
    
    
   cout<<"this is a operator +"<<endl;
   Point n;
   n.x = p1.x + p2.x;
   n.y = p1.y + p2.y;
   return n;
}

通过重载,就可以实现类的相加了

有趣的现象

b = a++;
(先执行 b = a,再执行 a = a+1)
b = ++a;
(先执行 a = a + 1,再执行 b = a)
自加的重载实现

class Point
{
    
    
   private:
     int x;
     int y;
   ...
};

/* Point p(1,2); ++p */
Point &operator++(Point &p)
{
    
    
   cout<<"++p"<<endl;
   p.x += 1;
   p.y += 1;
   return p;
}

/* Point p(1,2); p++ */
Point operator++(Point &p, int a)
{
    
    
   cout<<"p++"<<endl;
   Point n;
   n = p
   p.x += 1;
   p.y += 1;
   return n;
}

++p和p++进行重载时函数名一模一样,通过什么来区分?

答:通过传入不同参数来区分

在++p的重载函数和p++的重载函数中的返回值为什么不一样?为什么++p的返回值要以引用的形式出现?

首先在Point类的构造函数和析构函数里面加入打印信息

class Point
{
    
    
   private:
     int x;
     int y;
   public:
     Point()
     {
    
    
       cout<<"Point()"<<endl;
     }
     
     Point(int x, int y) : x(x), y(y)
     {
    
    
       cout<<"Point(int x, int y)"<<endl;
       printInfo();
     }
     
     /* 拷贝构造函数 */
     Point(const Point &p)
     {
    
    
       cout<<"Point(const Point &p)"<<endl;
       x = p.x;
       y = p.y;
     }
     
     ~Point()
     {
    
    
       cout<<"~Point()"<<endl;
     }     
     ...
};

接下来看一下主程序

int main()
{
    
    
  Point p(1, 2);
  cout<<"begin"<<endl;
  p++;
  cout<<"万能的分隔符"<<endl;
  ++p;
  cout<<"end"<<endl;
  return 0;
}

程序运行结果如下

 Point(int x, int y)
 (1, 2)
 begin
 p++
 Point()
 Point(const Point&p)
 ~Point()
 ~Point()
 万能的分隔符
 ++p
 end
 ~Point()

下面对运行结果进行逐行分析
1:执行Point p(1, 2)这句时,进入构造函数
2:构造函数Point(int x, int y)里面的打印信息
3:main函数里面的打印信息
4:执行p++时,程序跳转到函数operator++(p++)里面的打印信息
5: operator++(p++) 里面的Point n,新建了一个对象,产生的构造函数里执行的打印信息
6: operator++(p++) 函数里面对象p的生成时调用了拷贝构造函数(拷贝构造函数不在本次讨论过程中),从而打印信息
7,8:依次销毁对象p和对象n,调用了析构函数
9:main函数里万能的分隔符
10:执行++p时,程序跳转到函数operator++(++p) 里面的打印信息
11:main函数里面的打印信息
12:销毁main函数里面一开始创建的对象p时调用析构函数产生的打印信息

根据以上的分析,或许你已经得到了答案

为什么要用引用返回?

当你函数需要返回值时,上述的p++ 是进行值返回,需要依靠拷贝构造函数创建对象,然后返回对象的值,最后把对象销毁。由此可见,在它创建对象的那个过程,白白浪费了资源。上述的++p是进行引用返回,省去了创建新对象的过程,直接通过引用传入对象的地址,从而不会浪费空间资源。

既然引用返回那么好用,为什么p++不使用引用返回?

我们继续对如下代码分析

Point operator++(Point &p, int a)
{
    
    
  cout<<"p++"<<endl;
  Point n;
  n = p;
  
  p.x += 1;
  p.y += 1;

  return n;
}

这里的Point n申请的变量存储在栈空间中,当这个函数结束后就会释放内存。如果这个时候你想使用引用返回,相当于它将这片地址返回给调用它的程序。然而,在函数结束时,这片地址所指向的内存已经释放掉了,如果你采用引用返回,就会出现异常。所以,在这里使用引用返回是不妥的。

猜你喜欢

转载自blog.csdn.net/Stone831143/article/details/110253335