1. 程式人生 > >自增和自減操作符

自增和自減操作符

自增(++)和自減(--)操作符為物件加1和減1操作提供了方便簡短的實現方式.它們有前置或後置兩種使用形式.到目前為止,我們已經使用過前自增操作,該操作使其運算元加1,操作結果是修改後(changed)的值.同理,前自減操作使其運算元減1.這兩種操作符的後置形式同樣對其運算元加1(或減1),但操作後產生運算元原來的、未修改的值作為表示式的結果:

int i=0,j;
j=++i;//j=1,i=1:prefix yields incremented value
j=i++;//j=1,i=2:postfix yields unincremented value

因為前置操作返回加1後的值,所以返回物件本身,這是左值.而後置操作返回的則是右值.(也就是說,前置自增是先自增,然後操作賦值之類的,而後置自增可以理解為先操作,再自增.)

--------------------------------------------------我是華麗的分割線------------------------------------------------------

建議:只有在必要時才使用後置操作符

有使用C語言背景的讀者可能會覺得奇怪,為什麼要在程式中使用前自增操作.道理很簡單:因為前置操作需要做的工作更少,只需加1後返回加1後的結果即可.而後置操作則必須先儲存運算元原來的值,以便返回未加1之前的值作為操作的結果.對於int型物件和指標,編譯器可優化掉這項額外工作.但是對於更多的複雜迭代器型別,這種額外工作可能會花費更大的代價.因此,養成使用前置操作這個好習慣,就不必操心效能差異的問題.

---------------------------------------------------我是華麗的分割線-----------------------------------------------------

1.後置操作符返回未加1的值.

當我們希望在單個複合表示式中使用變數的當前值,然後再加1時,通常會使用後置的++和--操作:

vector<int> ivec;  //empty vector
int cnt=10;
//add elements 10...1 to ivec
while(cnt>0)
ivec.push_back(cnt--);  //int postfix decrement

這段程式使用了後置的--操作實現cnt減1.我們希望把cnt的值賦給vector物件的下一個元素,然後在下次迭代前cnt的值減1.如果在迴圈中使用前置操作,則是用cnt減1後的值建立ivec的新元素,結果是將9至0十個元素依次新增到ivec中.

2.在單個表示式中組合使用解引用和自增操作

下面的程式使用了一種非常通用的C++程式設計模式輸出ivec的內容:

vector<int>::iterator iter=ivec.begin();
//prints 10 9 8...1
while(iter !=ivec.end())
cout<<*iter++<<endl; //iterator postfix increment

由於後自增操作的優先順序高於解引用操作,因此*iter++等效於*(iter++).子表示式iter++使iter加1,然後返回iter原值的副本作為該表示式的結果.因此,解引用操作*的運算元是iter未加1前的副本.

這種用法的根據在於後自增操作返回其運算元原值(沒有加1)的副本.如果返回的是加1後的值,則解引用該值將導致錯誤的結果:ivec的第一個元素沒有輸出,並企圖對一個多餘的元素進行解引用.

------------------------------------------------------------------------我是飢餓的分割線----------------------------------

小心:如果程式設計師對C++和C語言都不太熟悉,則常常會弄不清楚表示式*iter++的含義.

建議:簡潔即是美

沒有C語言基礎的C++新手,時常會因精簡的表示式而苦惱,特別是像*iter++這類令人困惑的表示式.有經驗的C++程式設計師非常重視簡練,他們更喜歡這麼寫:

cout<<*iter++<<endl;

而不採用下面這種冗長的等效程式碼:

cout<<*iter<<endl;

++iter;

對於初學C++的程式設計師來說,第二種形式更清晰,因為給迭代器加1和獲取輸出值這兩個操作是分開來實現的.但是更多的C++程式設計師更習慣使用第一種形式.

要不斷地研究類似的程式碼,最後達到一目瞭然的地步.大部分的C++程式設計師更喜歡使用簡潔的表示式而非冗長的等效表示式.因此,C++程式設計師必須熟悉這種用法.而且,一旦熟悉了這類表示式,我們會發現使用起來更不容易出錯.

----------------------------------------------------我是飢餓的分割線---------------------------------------------------

習題5.15 解釋前自增操作和後自增操作的差別.

前自增操作和後自增操作都使其運算元加1,二者的差別在於:前自增操作將修改後運算元的值作為表示式的結果值;而後自增操作將運算元原來的、未修改的值作為表示式的結果值

習題5.16  你認為為什麼C++不叫做++C?

C++之名是Rick Mascitti在1983年夏天定名的,C說明它本質上是從C語言演化而來的,"++"是C語言的自增操作符.C||語言是C語言的超集,是在C語言基礎上進行的擴充套件(引入了new、delete等C語言中沒有的操作符,增加了對面向物件程式設計的直接支援,等等),是先有C語言,再進行++,根據自增操作符前、後置形式的差別,C++表示對C語言進行擴充套件之後,還可以使用C語言的內容;而寫成++C則表示無法再使用C的原始值了,也就是說C++不能向下相容C了,這與實際情況不符.

習題5.17  如果輸出vector內容的while迴圈使用前自增操作符,那會怎麼樣?

如果返回的是加1後的值,則解引用該值將導致錯誤的結果:ivec的第一個元素沒有輸出,並企圖對一個多餘的元素進行解引用

隨便黏貼一段程式:

#include<iostream>
using namespace std;
void reset(int *ip)
{
 *ip=0;
 ip=NULL;
}
void main()
{
 int i=42;
 int *p=&i;
 cout<<"i:"<<*p<<'/n';
 reset(p);
 cout<<"i:"<<*p<<endl;
 p=NULL;
 cout<<"i:"<<*p<<endl;
}