自增、自減的前綴即先增/減后取回
,后綴則是取回然后增/減
。
運算符重載差異
為了區分前綴和后綴,后綴形式的重載函數有int
型參數,在調用處編譯器會傳一個0
作為函數參數。這個參數沒有實際用途,為了避免編譯器對未使用參數的警告,應避免在聲明和實現給這個參數命名。
class UPInt{
public:
UPInt & operator++(); //++前綴
const UPInt operator++(int); //++后綴 省略參數名
UPInt & operator--(); //--前綴
const UPInt operator--(int); //--后綴
};
除了在參數,還需要注意返回類型和實現方式的不同。
UPInt & UPInt::operator++()//++前綴
{
*this += 1;//自增
return *this;
}
const UPInt UPInt::operator++(int)//++后綴
{
UPInt old = *this;//拷貝原值
++(*this);//自增
return old;//返回原值
}
前綴形式在處理自增后直接返回。而后綴形式首先拷貝原值,進行自增操作后返回原值的拷貝。返回的拷貝值是常量,目的是避免連續的后綴自增/自減運算。
UPInt++++
相當於UPInt.opeator(0)++.operator(0)++
,第二步自增運算符是對UPInt
的拷貝做運算,實際UPInt
只自增了一次,這和看起來有明顯差異。同時,C++也不允許對內置類型做連續的后綴自增/自減操作,后綴運算符重載函數也應返回常量以和內置類型保持一致。
效率差異
后綴形式的重載函數有一次拷貝操作,需要臨時對象保持原值。對於內置類型后綴自增運算符相比前綴有額外的一拷貝指令。
mov DWORD PTR [rbp-4], 10
#前綴自增
add DWORD PTR [rbp-4], 1 #值+1
mov eax, DWORD PTR [rbp-4]
mov DWORD PTR [rbp-8], eax
#后綴自增
mov eax, DWORD PTR [rbp-4] #拷貝到eax
lea edx, [rax+1] #值+1
mov DWORD PTR [rbp-4], edx #移動自增后的值到eax
mov DWORD PTR [rbp-8], eax #移動原值到edx
可見,前綴形式的自增運算符效率更高。無論是內置類型還是用戶定義類型,都應盡量使用前綴形式的自增/自減運算符。