標籤:

既然建議盡量避免使用goto語句為何C++還要支持goto呢?

既然已經證明了三種控制結構足以完成各種流程式控制制,C++為何還要保留goto這種「問題兒童」?


據說有種語言,好像是Prolog,去掉了goto,但引入了一個新的關鍵字叫come from。結果更亂了。


C++一開始設計時是要和C兼容的,當然不能把goto去掉,因為很多C程序都用了goto,尤其是系統底層。

goto也不是一無是處,在很深的循環嵌套層次中想跳到最外圍,用goto是很方便的。否則只能break一層一層跳。Java也保留了這種用法,不過換了語法變成break label;


只是讓你謹慎使用,而不是禁止使用

goto用好了可以讓代碼更加靈活,比如上面的例子

但是對於大多數人而言,用好很困難,如果使用不當,反倒有可能使的代碼的邏輯混亂

就像走鋼絲,走好了很好看,但大多數人走不好

所以需要謹慎使用,為了保險,不用也可以


後門永遠都是要開的。只是本來語言應該讓容易出問題的feature變得難寫,goto這個太容易了,要我的話就把關鍵字設計成:jump_to_the_specified_label_with_the_danger_of_jump_across_some_initialize_code xx;


for(...){for(...){for(...){for(...){for(...){for(...){

if(...) goto:outside;

}}}}}}

outside:


「三種控制結構足以完成各種流程式控制制」並不是說它們能簡潔地解決所有問題。就好比C已經是一個完備的語言,那為什麼還要C++、C#、Java、Python?


1 是為了與C語言兼容

2 其實for,while之類的循環,就是用goto來實現的,switch也可以用goto來實現。

for,while之類的控制語句會被翻譯成各類jmp系列的代碼。

有時候會發現,被編譯轉化後,效率有一點提高。但是代碼優化能主動進行就不要依賴於編譯器(因為不同編譯器的優化行為不一定一致),所以保留goto可以做一些優化,而又不至於直接嵌入彙編語言。

例如,下面的片段,可以完全用goto表現出來。(順便省掉了!=)

if(a==1)

{

cout&<&<"if brach"&<& }

else

{

cout&<&<"else branch"&<& }

cout&<&<"out"&<&

可以轉換成

if((a==1)==false)

goto lable1;

cout&<&<"else brach"&<& label1:

cout&<&<"if branch"&<& cout&<&<"out"&<&

3 作為2)的逆過程,當你想寫一個工具,把編譯後的中間文件或者最終文件反編譯會代碼的時候,你會發現goto其實是一個神器。

4 在c/c++中,goto是不能出函數域的。要跨函數goto可以使用long jump。


覺得一個東西對自己沒什麼用就非要刪掉它是手賤的一種表現。


有時候goto會使代碼更易懂

void func() {
int* p1 = new int;
char* p2 = nullptr;

if (xx)
goto cleanup;

p2 = new char;
if (xxx)
goto cleanup;

cleanup:
if (p1) {
delete p1;
p1 = nullptr;
}
if (p2) {
delete p2;
p2 = nullptr;
}
}


做source to source compiler的時候直接產生goto語句可以極大簡化編譯器開發。


goto語句的設計自身是沒問題的,之所以建議避免,我覺得這是一個軟體工程的問題。比如說,容易破壞代碼的模塊化組織結構,容易降低代碼的可讀性,以及代碼增長到一定規模後的可控性等等。畢竟,在一個團隊中,項目的代碼不總是一個人維護的,你的goto你懂,但不代表別人也懂,而且大家技術水平以及對代碼的理解誰也不能保證步調一致,濫用goto,會提升項目出現bug的概率。


在某些遊戲引擎里,goto用來簡化初始化代碼

雖然我不喜歡這種寫法,但實際效果看,確實減少了工作量


你的這種印象只不過是學校里缺乏工程經驗的老師照本宣科式的教育。他們自己都根本不知道goto有什麼用處。只是他們的老師告訴他們,goto很危險,不要用。

不要說goto了

我公司里有用jump 和long jump的底層代碼


有一些trick只有goto才能比較方便地實現,我在OS內核設計里就見到過。goto 是一種無條件跳轉,如果你對自己的程序運行包括棧的變化在內的情況了如指掌,goto隨便用無壓力。


雖然我從不寫goto,但我堅決支持goto!

好吧,保留goto就是為了兼容舊代碼,通俗滴說就是為了討好用戶


那個所謂的證明是扯淡的,我還可以證明if和goto能完成所有控制結構呢,然並卵。

早期結構化編程的一些思想已經落後於生產實踐,應該被拋棄。


真是決心要用了,內嵌彙編平衡棧用jmp也要用。防不住的。

我倒喜歡這種語言,不替人思考加一些限制,而是如實的交代底層操作並讓人選擇。


當作是一種「大招」來理解吧,內力不夠深厚的人不要隨便放否則未傷敵先傷己,而有著不錯內力的人放好了將會有很不錯的效果


可以使用goto語句,但是不濫用goto語句,goto語句在處理異常和異常清理工作更是代碼看起來更加清晰整潔,而且出錯處理的很好


被書誤導了,高空滑翔有危險,所以大家不要玩滑翔,但不能完全禁止。有很多功能不用goto會代碼更複雜,我在做腳本語言解析的時候必須要用到goto。


推薦閱讀:

c++ ,如何按照不同的要求調用標準庫sort函數排序?
在C#中,如何實現跟native dll 中途的線程間通信?
學C#需要學好C++么?
c++中子函數的局部變數在函數結束後是否會銷毀變數的內容?
c++中在局部空間用new運算符創建的變數是否會被銷毀?

TAG:編程 | C | CC |