C++學習筆記(二) 運算子過載

Chicken_Bird發表於2020-11-28

操作符過載

定義:讓加減乘除,不侷限於整型數的操作,也可以實現類的相加…

例項:

加法過載
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申請的變數儲存在棧空間中,當這個函式結束後就會釋放記憶體。如果這個時候你想使用引用返回,相當於它將這片地址返回給呼叫它的程式。然而,在函式結束時,這片地址所指向的記憶體已經釋放掉了,如果你採用引用返回,就會出現異常。所以,在這裡使用引用返回是不妥的。

相關文章