用C++編程的都知道,C++提供了一個非常強大的操作符重載機制,利用操作符重載,我們可以為我們自定義的類增加更多非常有用的功能。不過,C++也有限制,就是當我們為自定義的類重載操作符時,重載操作符的含義應該跟內置類型一樣,比如,你不能通過重載+號操作符來實現兩個數相乘的運算,實現需要是兩個數相加的運算。本篇,我重點介紹下重載前置++和后置++的區別(前置--跟后置--類似)。
我們知道,寫for循環年的時候,可以用下面這兩種方式:
for(int i=0; i<10; i++) { //do something } for(int j=0; j<10; ++j) { //do something }
如上兩種方式,i++跟++j到底有什么區別呢?
首先,這兩種方式都會使得i跟j自增1, 不同的地方在於其內部實現; i++的實現原理是現將i自增1,然后返回i的引用(我們知道重載操作符也是可以有返回值的);而++j的實現原理是:先定義一個j的副本,然后在將j自增1,最后返回之前定義個那個副本的值。
通常,c++的內置類型都要求前綴式操作符返回被增量或被減量對象的引用;而要求后綴式操作符返回被增量活被減量對象做增或減操作之前的副本(這里邊就存在內存拷貝)。
實際的調用過程看起來應該是這樣:
for( int i=0; i<10; i.operator++(0) ) { //調用后置++ //do something } for( int i=0; i<10; i.operator++() ) { //調用前置++ //do something }
看到這里,你可能 有個疑問,為什么調用后置++的之后,參數列表要傳一個0而前置++卻沒有傳呢?
這里就牽扯出前置++跟后置++的另一個差別。
前置++和后置++在定義的都是一樣,看起來應該是下邊這樣:
class A { private: int a; public: A& operator++() { //... } A operator++() { //... } }
這樣,我們就無法區分到底哪個是哪個了,也許你會說它們的返回值不是不一樣嗎? 我們老早就知道,無法通過不同的返回值來重載不同的函數版本。
這種情況下,為了做區分也是為了解決這一問題,一般要求后綴式操作符接受一個額外的int型形參(不會使用它,僅做區分用),來區別兩者的不同。
class A { private: int a; public: A& operator++() { //前置++ //... } A operator++(int) { //后置++ //... } }
這樣,編譯器將為我們提供0作為這個后綴式版本的形參。(也可以調用這個有參數的版本做前綴式操作,不過一般不應該這么做),下邊是完整定義:
class A { private: int a; public: A& operator++() { //前置++ ++a; return *this; } A operator++(int) { //后置++ A a = *this; ++*this; returnn a; } }
如上,操作符的后綴式比前綴式復雜一些,在實現后綴式版本時,一般先保存對象做自增/減之前的副本,然后調用自己的前綴版本來實現自增操作,最后將先前年保留的副本
返回。這里需要注意的是,后綴式版本中,返回值是尚未自增的原值,但對象本身已經做了自增操作了。
( ps : --操作符的前綴式和后綴式類型)