1. 程式人生 > >【C++】前置操作符(++i)和後置操作符(i++)

【C++】前置操作符(++i)和後置操作符(i++)

 一、自增和自減的基本使用方法

自增的兩種形式: 

i++ i 的值作為返回值,i 自增 1;
++i i 自增 1,i 的值作為返回值。

Example:

#include <iostream>
#include <string>

using namespace std;

int main()
{
	int i = 0;

	i++;

	++i;

	getchar();
	return 0;
}

 檢視上面程式碼段的彙編程式碼:

	i++;
00931765  mov         eax,dword ptr [i]  
00931768  add         eax,1  
0093176B  mov         dword ptr [i],eax  

	++i;
0093176E  mov         eax,dword ptr [i]  
00931771  add         eax,1  
00931774  mov         dword ptr [i],eax  

可見,兩個操作方式的彙編彙編程式碼完全相同,只是存放的暫存器不同。主要原因是編譯器對其做了優化。

1、現代編譯器產品會對程式碼進行優化;
2、優化使得最終的二進位制程式更加高效;
3、優化後的二進位制程式丟失了C/C++的原生語義;
4、不可能從編譯後的二進位制程式還原C/C++程式。

二、自增自減面試題

接下來看一道經典的面試題:

Question :考慮下面的兩個程式碼片段來列印vector。其中一個與另一個有什麼優勢嗎?

選項1:

vector vec;
/* ... .. ... */
for (auto itr = vec.begin(); itr != vec.end(); itr++) {
	itr->print();
}

選項2:

vector vec;
/* ... .. ... */
for (auto itr = vec.begin(); itr != vec.end(); ++itr) {
	itr->print();
}

Explanation :

  雖然兩種選項都可以完全相同,但從效能的角度來看,第二種選擇更好。 這是因為後增操作符(即itr ++)比前增操作符(即++ itr)更昂貴。 後增操作符的底層實現在遞增之前建立元素的拷貝,然後返回拷貝。 也就是說,許多編譯器會自動優化第一個選項,將其轉換為第二個選項。

三、 ++ 操作符過載

1.全域性函式和成員函式均可進行過載
2.過載前置 ++ 操作符不需要額外的引數
3.過載後置 ++ 操作符需要一個int型別的佔位引數

Example:根據C++中的原生語義過載 ++ 操作符

#include <iostream>
#include <string>

using namespace std;

class Test
{
    int mValue;
public:
    Test(int i)
    {
        mValue = i;
    }
    
    int value()
    {
        return mValue;
    }
    
    Test& operator ++ ()
    {
        ++mValue;
        
        return *this;  //返回引用
    } 
    
    Test operator ++ (int) //後置++
    {
        Test ret(mValue); //將當前的值先儲存下來
        
        mValue++;  //將當前物件自增1
        
        return ret;  //返回當前物件 
    }
};

int main()
{
    Test t(0);
    
    t++;  //需要呼叫建構函式和解構函式
    
    ++t; //效率更高,沒有生成額外的物件
         //意味著不需要呼叫棧上的記憶體,
		 //不需要呼叫建構函式、解構函式
    return 0;
}

四、總結:++ i 和 i ++  真正的區別...

對於基礎型別的變數

1.前置 ++ 的效率與後置 ++ 的效率基本相同
2.根據專案組編碼規範進行選擇

對於類型別的物件

1.前置 ++ 的效率高於後置 ++
2.儘量使用前置 ++ 操作符提高程式效率

Reference: