比較這二種迴圈時,應先講述locality of declaration的原由,以下的範例節自c++ primer 3th。
ex:
#include<fstream>
#include<string>
#inclue<vector>
using namespace std;
int main()
{
string fileName;
cout<<"please enter name of file to open: ";
cin>>fileName;
if(fileName.empty())
{
cerr<<"fileName is empty().bailing out.bye!\n";
return -2;
}
ifstream inFile( fileName.c_str() ); // #2
if ( ! inFile )
{
cerr << "unable to open file. bailing out. bye!\n";
return -2;
}
string inBuf; // #3
vector< string > text; // #4
....//略
}
這個程式有7個declaration(宣告式)和8個object definition(定義式)。Declaration述句可以表現出所謂的locality of declaration(宣告的區域性),也就是說declaration述句可以在「它所定義之object初次被使用」的場合(才)現身。
1970年代,電腦程式語言的設計哲學強調:在任何程式述句出現之前,於程式、函數、述句區段的起頭處先定義所有的object,由於C++將object define視為述句(宣告述句),所以可以置於一孺述句可出現的任何地點。從文法上而言,這告就了locality of declaration的可能性。
真的有如此必要嗎?對於內建型別如整數或浮點數,locality of declaration 可能只關係到個人喜好而已,C++語言鼓勵大家在if、else-if、switch、while和for的條件式中使用locality of declaration(如前例所呈現的)。愛用locality of declaration 的人相信,它可以讓程式更容易解讀。
但當class擁有相應的constructors和destructor時,其objec definition 就很迫切需要locality of declaration性質了。如果我們把這類class objects 放置在函數、述句區段的起頭,會發生兩件事:
1.在此函數或述句區段做任何事之前,所以class objects的相應constructor全都會被喚起,locality of decalartion讓我們得以在函數或述句區段的整個範圍內,分期攤還初始化所需成本。
2.或許更重要的是函數或述句區段常常會在其中每個述句都執行過之前,就半途結束了。例如稍早的程式就出現在有兩個不正常的結束點(1)檔名為空,(2)開檔失敗。在這些結束點之前定義出尚未用到的class object,例如inbuf 和text,會導至非必要的constructor-destructor執行動作。如果這樣的class object極多,或是其constructor和destructor的執行十分秏時,我們實在沒有必要這般衝擊我們程式的執行效率。是的,程式結果仍然正確,但效率有時候會變得無法忍受。
現在回到我的主題,for迴圈述句比while迴圈述句更具備locality fo decalartion。
我先描敘for、while的定義
1 for迴圈述句定義如下:
for(init-statement;condition;expression)
statement;
2 while迴圈述句定義如下:
while(condition)
statement;
我們用以下的例子來講述我的想法
#include <iostream>
class testc
{ public:
testc(){std::cout<<"constructor"<<std::endl;}
~testc(){std::cout<<"destructor"<<std::endl;}
testc(int c){std::cout<<"constructor"<<std::endl;}
operator int(){return 10;}
};
using namespace std;
int main()
{
std::cout << "Hello world!" << std::endl;
for(testc b=10;;)
;
while(testc b=10)
;
/*
或者
while(true)
{
testc b=10;
}
*/
return 0;
}
執行此程式顯而易見的,當我想要達到locality of declaration的效果時,for迴圈中b變數只須要定義一次、初始化一次(constructor-destructor只執行一次),
但while迴圈中b變數會依迴圈執行的次數,被多次重新定義、多次初始化(constructor-destructor執行多次),造成效能降低。
由於for迴圈述句本身定義造就了更容易達成locality of declaration的效果,但想要在while迴圈中達到localtiy of declaration效果並不是不可能的行為,我們可以使用一對大括號來達到locality fo declaration,如下:
{
testc b=10;//locality of declaration的效果
while(true)
;
}
最後,我在這裡是討論for迴圈述句與while迴圈述句的locality of declaration效果差異,雖然我們都知道我們會依據場合來選擇使用for或while。