C++/Object Pascal中迴圈結構的一點差異及討論 (轉)
C++/ Pascal中迴圈結構的一點差異及討論
:namespace prefix = o ns = "urn:schemas--com::office" />
雖然在所有的語言之中,的都無非是順序、分支和迴圈等幾種結構,比如說,C中的if…else,switch…case,while和do…while, 以及Pascal中的if…then…else,case…of,while…do,repeat…until,幾乎就是一一對應的關係,只不過語法上有小小的差異而已。這樣的相似性使得我們在掌握一門語言之後,再學習其他語言就容易得多了。然而,語言之間的不同是細微而瑣碎的,如果不注意這些差別的話,它們遲早會從不知哪個角落跳出來,讓程式設計師陷入de的噩夢。
讓我們來看一個例子。我們知道在一般的迴圈結構中,fo迴圈和while迴圈是可以轉換的,例如,在Pascal中
for I:=StartValue to EndValue do …;
可以轉換成相應的while 迴圈:
I:=StartValue;
while I<=EndValue do begin
…;
Inc(I);
end;
看起來,這兩種迴圈是完全一樣的。別忙,真的完全一樣嗎?下面是一段程式碼,你可以先心算一下,看得出來的結果應該是多少:
procedure TForm1.FormCreate(Sender: TObject);
var
i, j : integer;
index : integer;
str : string;
begin
i := 0;
j := 3;
for index:=0 to j do begin
Inc(i);
if j<5 then Inc(j);
end;
str := IntToStr(i);
i := 0;
j := 3;
index := 0;
while index<=j do begin
Inc(i);
if (j<5) then Inc(j);
Inc(index);
end;
Caption := str + ',' + IntToStr(i);
end;
雖然兩個迴圈看起來完全沒有差別,執行後結果卻截然不同:一個是4,一個是6。
我們先不忙討論其中的原因,再來看看在C語言中情況如何。
void CTestDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
int i, j;
int index;
i = 0;
j = 3;
for (index=0;index<=j;index++)
{
i++;
if (j<5) j++;
}
CString str;
str.Format( "%d", i );
SetWindowText(str);
CDialog::OnLButtonDown(nFlags, point);
}
void CTestDlg::OnRButtonDown(UINT nFlags, CPoint point)
{
int i, j;
int index;
i = 0;
j = 3;
index = 0;
while (index<=j)
{
i++;
if (j<5) j++;
index++;
}
CString str;
str.Format( "%d", i );
SetWindowText( str );
CDialog::OnRButtonDown(nFlags, point);
}
答案如何呢?在Visual C++中,兩個結果都是6。
為了排除對程式執行結果的影響,我在Delphi和Visual C++中分別執行不最佳化的程式和最佳化後的程式,結果也是一樣的:Delphi中兩段迴圈的結果分別是4和6,而在Visual C++中,兩個迴圈結果都是6。
以上的試驗我是在 SE,Delphi 6.0和Visual C++6.0的環境下測試的。如果你感興趣的話,也可以換VB,或者C++Builder或者其他環境來測試一下,看得出的結果如何。
看來現在可以得出答案了。之所以在Delphi中兩個結果會有所不同,是因為我們在迴圈中改變了變數j的值,而j又用來作為測試迴圈終止的條件。我們可以得出這樣的結論:
1.在Object Pascal中,for迴圈和while迴圈對於迴圈如何終止的條件是有差別的。for迴圈在每次迴圈後不會對終止條件再次求值,也就是說,任何一個for迴圈已開始,總共的迴圈次數就已經確定了,即使你想改變也辦不到。而while迴圈的執行次數是不定的,你可以在迴圈體中隨時改變迴圈次數。
2.由於處理方法不同,因此在執行上也相應的有所不同。在Object Pascal Language Gu中已經指明瞭這一點。下面是該書第四章《語法元素》中的一段話:
The difference between this construction and the for...to statement is that the while l re-evaluates finalValue before each iteration. This can result in noticeably slower performance if finalValue is a complex expression, and it also means that changes to the value of finalValue within statement can affect execution of the loop.
可見,由於每次迴圈後都要對迴圈條件重新求值,因此while迴圈的執行效率明顯低於for。因此,如何可能的話,應該儘量多使用for迴圈。為了提高效率,迴圈條件應儘量簡單,能用常量的地方一定要使用常量。
3.在C語言(嚴格的說,上述情況只在Visual C++中驗證過;在其他C環境如C++Builder和GCC中尚未驗證)中,for和while迴圈的處理方法是一致的:在每次迴圈後都要重新求值。
就效率而言,如果迴圈條件中使用的是變數而非常量,特別是迴圈條件是一個比較複雜的的時候,那麼C中的for迴圈應該是比Object Pascal中的for迴圈效率要低一點(僅僅是理論上講)。
4.知道了for和while迴圈在不同語言中的表現,我們就知道應該如何在編寫迴圈的時候避免一些錯誤。例如,下面的程式碼在Delphi中不會有問題:
var
sl : TStringList;
I : integer;
begin
sl := TStringList.Create;
sl.Add(‘1’);
sl.Add(‘2’);
for I:=0 to sl.Count do sl.Add(‘temp string’);
而在VC中,這樣的程式碼就會讓程式進入死迴圈:
CStringArray sa;
sa.Add(“1’);
sa.Add(“2”);
for (int I=0;I sa.Add(“temp string”); 在我的機器上,這一段程式在長時間的執行後終於彈出一個“不足”的對話方塊,而這時幾乎所有正在執行的程式都慢的好像龜爬了。希望在你的程式中不會看到這種讓人不快的現象。 後記:儘管for迴圈和while迴圈的這種微小的差別並不如何令人感興趣,但是一個嚴謹的程式設計師應該知道這些細節。有些程式設計師迷戀於各種各樣讓自己的程式漂亮起來的小,而對程式語言本身的許多東西卻忽略掉了。隨著許多非科班出身的愛好者加入程式設計隊伍,一些不好和不正規的程式設計習慣以及捨本逐末的做法也蔓延開來,流風所及,很少人不受到影響。如果我不是正在啃Object Pascal Language Guide的話,根本不會注意到這麼小的地方,也不會想到我原本以為自己很熟悉了的Pascal語言中還隱藏著一些不為人知的東西。C++也是如此,關心 How to put a icon into the system tray的人,似乎永遠比關心 why the class should have a virtual destructor的人來的多。 基本功不怕深厚,只怕太淺。我的希望是,對於所謂XX天精通XXX,或者XXX從到精通之類的東西,大家還是少看為妙,多花一些時間,靜下心來讀些實實在在的技術資料,比什麼都強,雖然讀到頭皮發麻精力不濟的時候所在多有,但是隻要認真過一遍,你的層次絕對不同。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-991400/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- C++中的迴圈結構C++
- Object Pascal中String型別的內幕探討 (轉)Object型別
- plsql--迴圈討論SQL
- 資料結構學習(C++)——迴圈連結串列 (轉)資料結構C++
- 對於 JavaScript 中迴圈之間的技術差異概述JavaScript
- Object Pascal Style Guide (轉)ObjectGUIIDE
- 迴圈結構for
- 迴圈結構
- Java迴圈結構-for,while及do…whileJavaWhile
- 【資料結構】雙迴圈連結串列(c++)資料結構C++
- 探討兩種迴圈表示方法的區別,while迴圈與for迴圈的小總結While
- 【資料結構】實現迴圈連結串列(c++)資料結構C++
- 【資料結構】迴圈佇列的實現(c++)資料結構佇列C++
- Java 迴圈結構 - for, while 及 do...whileJavaWhile
- c++中的一些迴圈語法C++
- 05迴圈結構
- py迴圈結構
- 一個簡易的渲染迴圈結構
- Java和C++的基本差異(轉)JavaC++
- C語言——迴圈結構(for迴圈,while迴圈,do-while迴圈)C語言While
- ruby 怪異的while迴圈處理,和java的差別WhileJava
- 中西IT差異論
- Object Pascal:從物件指標談起 (轉)Object物件指標
- Scala與Java差異(二)之條件控制與迴圈Java
- python分支結構與迴圈結構Python
- Java語言和C++語言的差異 (轉)JavaC++
- 比較兩個資料庫的表結構差異(轉)資料庫
- Python迴圈結構用法Python
- php分支和迴圈結構PHP
- 6、迴圈結構語句
- 迴圈結構程式設計程式設計
- 表結構設計討論
- Gradle中的差異化構建Gradle
- 淺談Object Pascal的指標Object指標
- 比較兩個的表結構差異
- C++:不同迴圈結構計算從1到100的累加和C++
- JavaScript(二):選擇、迴圈結構JavaScript
- 4.Python——迴圈結構Python