自增和自減操作符
自增(++)和自減(--)操作符為物件加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;
}