C++ goto語句的理解與應用

來源:互聯網
上載者:User

以下來自新浪部落格的轉載:

1:為何不提倡使用goto語句?

淵源(來自wikipedia):

GOTO是一條可以在許多電腦程式設計語言中找到的語句。它是英文單詞goto的組合。當執行這條語句的時候,它將控制流程程無條件地轉到另一條語句(也叫"跳轉")。跳躍陳述式需要指明標記,在不同語言中,標記可以是標識符或行號。在機器碼層級,goto是一種分支的形式。

在一些語言中,可以不用顯示地使用goto關鍵字而實現同樣的功能,例如break或continue關鍵字可以跟隨一個標識符。SNOBOL語言支援一種語句的尾碼形式,可以在本條語句執行完畢後實現無條件跳轉。

GOTO語句被大部分進階語言支援,只有很少的進階語言不支援GOTO語句。例如,goto是一個Java語言的保留字,但是不允許使用。例如Pascal中沒有Goto,但可用procedure執行一外加文法。

GOTO語句一直是批評和爭論的目標,主要的負面影響是使用GOTO語句使程式的可讀性變差,甚至成為不可維護的“麵條代碼”。隨著結構化編程在二十世紀六十年代到七十年代變得越來越流行,許多電腦科學家得出結論,即程式應當總是使用被稱為“結構化”控制流程程的命令,如迴圈以及if-then-else語句來替代GOTO。甚至在今天,許多程式風格編碼通訊協定禁止使用GOTO語句。為GOTO語句辯護的人認為,加以限制地使用GOTO語句不會導致低品質的代碼,並且聲稱在許多程式設計語言中,一些任務如果不使用一條或多條GOTO語句是無法被直接實現的。如有限狀態自動機的實現、跳出嵌套迴圈以及異常處理。

大概最著名的對於GOTO的批評是艾茲格·迪傑斯特拉(Edsger Wybe Dijkstra)在1968年的一篇名稱為《GOTO陳述有害論(英語:Go
To Statement Considered Harmful)》的論文。[2]迪傑斯特拉認為不加限制地使用GOTO語句應當從進階語言中廢止,因為它使分析和驗證程式正確性(特別是涉及迴圈)的任務變得複雜。另外一種觀點高德納的Structured
Programming with go to Statements
 [3]中,文章分析了許多常見編程任務,然後發現其中的一些使用GOTO將得到最理想的結構。

這些批評在一些程式設計語言的設計上起到了效果。雖然Ada語言的設計者在二十世紀七十年代晚期意識到了對於GOTO的批評,這條語句仍舊被包含進去,主要是用來支援自動產生那些goto語句必不可少的代碼。[4]但是,作為goto語句目的地的標籤必須使用雙角括弧括起來(如:<<Start_Again>>),而這個文法在其他語言中都不被使用。這使得檢查程式中goto目的地的存在變得容易。goto語句本身使用簡單的形式goto Start_Again;.


原因:  GOTO語句使程式的靜態結構和動態結構不一致,從而使程式難以理解,難以查錯。
有人認為GOTO語句使用起來比較靈活,而且有些情形能提高程式的效率。
1974年,D·E·克努斯對於GOTO語句爭論作了全面公正的評述,其基本觀點是:不加限制地使用GOTO語句,特別是使用往回跳的GOTO語句,會使程式結構難於理解,在這種情形,應盡量避免使用GOTO語句。但在另外一些情況下,為了提高程式的效率,同時又不至於破壞程式的良好結構,有控制地使用一些GOTO語句也是必要的。用他的話來說就是:“在有些情形,我主張刪掉GOTO語句;在另外一些情形,則主張引進GOTO語句。”
後來,G·加科皮尼和C·波姆從理論上證明了:任何程式都可以用順序、分支和重複結構表示出來。這個結論表明,從進階程式語言中去掉GOTO語句並不影響進階程式語言的編程能力,而且編寫的程式的結構更加清晰。
goto語句的結果:在C/C++等進階程式設計語言中保留了goto語句,但被建議不用或少用。在一些更新的進階程式設計語言,如Java不提供goto語句,它雖然指定goto作為關鍵字,但不支援它的使 用,使程式簡潔易讀;儘管如此後來的c#還是支援goto語句的,goto語句一個好處就是可以保證程式存在唯一的出口,避免了過於龐大的if嵌套。
可以考慮使用goto的情形:1.從多重迴圈中直接跳出 ;2. 出錯時清除資源; 3.可增加程式的清晰度的情況。
不加限制地使用goto:破壞了清晰的程式結構,使程式的可讀性變差,甚至成為不可維護的"麵條代碼"。經常帶來錯誤或隱患,比如它可能跳過了某些對象的構造、變數的初始化、重要的計算等語句。
goto語句問題的提出直接推動了結構化程式設計(structured programming)的思想和程式設計方法學的誕生和發展。結構化程式設計方法引入了工程思想和結構化思想,使大型軟體的開發和編程都得到了極大的改善。結構化程式設計方法的主要原則可以概括為自頂向下,逐步求精,模組化,限制使用goto語句。
下列關於使用goto語句的原則可以供讀者參考。   1) 使用goto語句只能goto到同一函數內,而不能從一個函數裡goto到另外一個函數裡。   2) 使用goto語句在同一函數內進行goto時,goto的起點應是函數內一段小功能的結束處,goto的目的label處應是函數內另外一段小功能的開始處。   3) 不能從一段複雜的執行狀態中的位置goto到另外一個位置,比如,從多重嵌套的迴圈判斷中跳出去就是不允許的。   4)應該避免像兩個方向跳轉。這樣最容易導致"麵條代碼"。

 2:網友熱心回答

goto並不是不能用,關鍵是goto指向的標籤必須在goto這行的後面。
盲目禁用goto是不對的。
見傑拉爾德·溫伯格《理解專業程式員》

如果要做軟體開發的話,特別是團隊的話,為了將來項目的維護和讓代碼通俗易懂,最好不要用goto;
goto會影響編譯器最佳化,還有九成的goto都可以轉換成不用goto的方式

如果GOTO的語句在後面就不會出現死迴圈!
如果GOTO的語句在前面就很容易死迴圈!!!
還有,GOTO  的語句都能用REPEAT或WHILE來代替!
所以,一般不用GOTO!!

因為那會擾亂編程結構次序

3:

正面:

goto語句在C/C++語言中可謂是“臭名昭著”,乃至有的書(或公司的編程規範)提出禁用goto語句的說法。其結果就是,造成有的程式員一看到goto語句在某程式中被使用,就本能地認為這個程式寫得很“垃圾”。此外,也使得有些程式員因為使用了goto語句而覺得自己很不專業。其實,凡事都不能太偏激,goto語句運用得好能大大地簡化程式,以及提高程式的可讀性和可維護性。在開始樣本其好處之前,先用一些統計資料來說明goto語句並沒有因為“臭名昭著”而被拋棄,這些統計資料可能並不是百分之百的精確,但很具有說服力。對於作業系統,Linux-2.6.21核心使用了20,333個goto語句,VxWorks-6.2則使用了9142個,最後941個goto語句被運用到了rtems-4.9.2中;另外,glibc-2.9庫使用了1750個goto語句。所有這些統計資料都表明,goto語言並沒有想象的那樣可怕而招到禁用,其關鍵在於
—— 恰當地運用它。

轉載來自:http://blog.sina.com.cn/s/blog_6908039c0101f5hx.html

 

以下來自csdn部落格的轉載:

goto只能在函數體內跳轉,不能跳到函數體外的函數。即goto有局部範圍,需要在同一個棧內。

需要在要跳轉到的程式段起始點加上標號。如下例中的part2。

1.goto 語句可用於跳出深嵌套迴圈

[cpp]
view plaincopyprint?
  1. #include<iostream>   
  2. using namespace std;  
  3. int main()  
  4. {  
  5. for(int i=0;i<10;i++)  
  6.  for(int j=0;j<10;j++)  
  7.   for(int k=0;k<10;k++)  
  8.   {  
  9.          cout<<i*j*k<<" ";  
  10.          if(216==i*j*k)  
  11.             goto part2;//break是跳不出多重迴圈的 
      
  12.          }  
  13.          cout<<"此處被省略"<<endl;      
  14.   part2:  
  15.        cout<<"part2"<<endl;  
  16.   system("pause");  
  17. }  
#include<iostream>using namespace std;int main(){for(int i=0;i<10;i++) for(int j=0;j<10;j++)  for(int k=0;k<10;k++)  {         cout<<i*j*k<<" ";         if(216==i*j*k)            goto part2;//break是跳不出多重迴圈的          }         cout<<"此處被省略"<<endl;      part2:       cout<<"part2"<<endl;  system("pause");}

2.goto語句可以往後跳,也可以往前跳

[cpp]
view plaincopyprint?
  1. #include<iostream>   
  2. using namespace std;  
  3.   
  4. int main()  
  5. {  
  6.     int x,sum=0;  
  7.     //定義標號L1   
  8. L1: cout<<"x=";  
  9.     cin>>x;  
  10.     if (x==-1)  
  11.        goto L2;          //當使用者輸入-1時,轉到L2語句處
      
  12.     else  
  13.        sum+=x;  
  14.     goto L1;             //只要使用者沒有輸入-1,則轉到L1語句處,程式一直將使用者的輸入默默地累加到變數sum中。
      
  15.     //定義標號L2   
  16. L2: cout<<"sum="<<sum<<endl;//一旦轉到L2,將輸出累計結果,程式運行結束。
      
  17.     system("pause");  
  18. }  
#include<iostream>using namespace std;int main(){    int x,sum=0;    //定義標號L1L1: cout<<"x=";    cin>>x;    if (x==-1)       goto L2;          //當使用者輸入-1時,轉到L2語句處    else       sum+=x;    goto L1;             //只要使用者沒有輸入-1,則轉到L1語句處,程式一直將使用者的輸入默默地累加到變數sum中。    //定義標號L2L2: cout<<"sum="<<sum<<endl;//一旦轉到L2,將輸出累計結果,程式運行結束。    system("pause");}

3.也可以跳出switch,或者在case之間進行跳轉

如:

[cpp]
view plaincopyprint?
  1. #include<iostream>   
  2. using namespace std;  
  3.   
  4. int main()  
  5. {  
  6. char a;  
  7. L1:  
  8. cout<<"請輸入一個字元"<<endl;  
  9. cin>>a;  
  10. switch(a)  
  11. {  
  12.   case 'a':  
  13.        cout<<"case a"<<endl;  
  14.        goto L1;  
  15.        //break;   
  16.   L2:  
  17.   case 'b':  
  18.        cout<<"case b"<<endl;  
  19.        break;  
  20.   case 'c':  
  21.        cout<<"case c"<<endl;  
  22.     //   break;   
  23.        goto L2;  
  24.   default:  
  25.           break;  
  26. }  
  27.   system("pause");  
  28. }  
  29.     
#include<iostream>using namespace std;int main(){char a;L1:cout<<"請輸入一個字元"<<endl;cin>>a;switch(a){  case 'a':       cout<<"case a"<<endl;       goto L1;       //break;  L2:  case 'b':       cout<<"case b"<<endl;       break;  case 'c':       cout<<"case c"<<endl;    //   break;       goto L2;  default:          break;}  system("pause");}  

轉載來自:http://blog.csdn.net/generalhking/article/details/8011306

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.