3 回答

TA貢獻(xiàn)1828條經(jīng)驗(yàn) 獲得超13個(gè)贊
有幾種方法,但首先你需要理解為什么對(duì)象清理很重要,因此std::exit
在C ++程序員中邊緣化的原因。
RAII和堆棧展開
C ++使用了一個(gè)名為RAII的習(xí)語,簡單來說就是對(duì)象應(yīng)該在構(gòu)造函數(shù)中執(zhí)行初始化并在析構(gòu)函數(shù)中進(jìn)行清理。例如,std::ofstream
類[可]在構(gòu)造函數(shù)中打開文件,然后用戶對(duì)其執(zhí)行輸出操作,最后在其生命周期結(jié)束時(shí)(通常由其作用域確定),調(diào)用析構(gòu)函數(shù),實(shí)質(zhì)上關(guān)閉文件并刷新任何書面內(nèi)容進(jìn)入磁盤。
如果你沒有到析構(gòu)函數(shù)刷新并關(guān)閉文件會(huì)發(fā)生什么?誰知道!但可能它不會(huì)寫入它應(yīng)該寫入文件的所有數(shù)據(jù)。
例如,考慮這段代碼
#include <fstream>#include <exception>#include <memory>void inner_mad(){ throw std::exception();}void mad(){ std::unique_ptr<int> ptr(new int); inner_mad();}int main(){ std::ofstream os("file.txt"); os << "Content!!!"; int possibility = /* either 1, 2, 3 or 4 */; if(possibility == 1) return 0; else if(possibility == 2) throw std::exception(); else if(possibility == 3) mad(); else if(possibility == 4) exit(0);}
每種可能性都會(huì)發(fā)生什么:
可能性1:返回基本上離開了當(dāng)前的函數(shù)范圍,因此它知道生命周期的結(jié)束
os
因此調(diào)用它的析構(gòu)函數(shù)并通過關(guān)閉并將文件刷新到磁盤來進(jìn)行適當(dāng)?shù)那謇怼?/p>可能性2:拋出異常也會(huì)處理當(dāng)前范圍內(nèi)對(duì)象的生命周期,從而進(jìn)行適當(dāng)?shù)那謇?.....
可能性3:這里堆疊展開進(jìn)入行動(dòng)!即使拋出異常
inner_mad
,展開器也將通過堆棧mad
并main
進(jìn)行適當(dāng)?shù)那謇?,所有?duì)象都將被正確破壞,包括ptr
和os
。可能性4:嗯,這里?
exit
是一個(gè)C函數(shù),它不知道也不兼容C ++習(xí)語。它不會(huì)對(duì)您的對(duì)象執(zhí)行清理,包括os
在相同的范圍內(nèi)。因此,您的文件將無法正常關(guān)閉,因此內(nèi)容可能永遠(yuǎn)不會(huì)寫入其中!其他可能性:它只是通過執(zhí)行隱式
return 0
而離開主范圍,因此具有與可能性1相同的效果,即適當(dāng)?shù)那謇怼?/p>
但是不要對(duì)我剛才告訴你的事情這么肯定(主要是可能性2和3); 繼續(xù)閱讀,我們將找到如何執(zhí)行適當(dāng)?shù)漠惓G謇怼?/p>
可能的方法結(jié)束
從主要回來!
你應(yīng)該盡可能地這樣做; 總是喜歡通過從main返回正確的退出狀態(tài)來從程序返回。
您的程序的調(diào)用者,可能還有操作系統(tǒng),可能想知道您的程序應(yīng)該執(zhí)行的操作是否成功。出于同樣的原因,您應(yīng)該返回零或EXIT_SUCCESS
表示程序成功終止并EXIT_FAILURE
發(fā)出程序終止失敗的信號(hào),任何其他形式的返回值都是實(shí)現(xiàn)定義的(第18.5 / 8節(jié))。
但是你可能在調(diào)用堆棧中非常深,并且返回所有這些可能會(huì)很痛苦......
[不]拋出異常
拋出異常將使用堆棧展開執(zhí)行正確的對(duì)象清理,方法是調(diào)用任何先前作用域中每個(gè)對(duì)象的析構(gòu)函數(shù)。
但這是抓住了!它是實(shí)現(xiàn) - 定義是否在未處理拋出異常時(shí)(通過catch(...)子句)執(zhí)行堆棧展開,或者即使noexcept
在調(diào)用堆棧中間有函數(shù)也是如此。這在§15.5.1[except.terminate]中說明:
在某些情況下,必須放棄異常處理以獲得不太精細(xì)的錯(cuò)誤處理技術(shù)。[注意:這些情況是:
[...]
- 當(dāng)異常處理機(jī)制找不到拋出異常的處理程序時(shí)(15.3),或者當(dāng)搜索處理程序(15.3)遇到函數(shù)的最外層塊時(shí),
noexcept
-specification不允許異常(15.4),或者[...][...]
在這種情況下,調(diào)用std :: terminate()(18.8.3)。在沒有找到匹配處理程序的情況下,無論是否在調(diào)用std :: terminate()之前展開堆棧,它都是實(shí)現(xiàn)定義的 [...]
所以我們必須抓住它!
拋出一個(gè)異常并在main處抓住它!
由于未捕獲的異??赡懿粓?zhí)行堆棧展開(因此不會(huì)執(zhí)行正確的清理),我們應(yīng)該在main中捕獲異常然后返回退出狀態(tài)(EXIT_SUCCESS
或EXIT_FAILURE
)。
所以一個(gè)可能很好的設(shè)置將是:
int main(){ /* ... */ try { // Insert code that will return by throwing a exception. } catch(const std::exception&) // Consider using a custom exception type for intentional { // throws. A good idea might be a `return_exception`. return EXIT_FAILURE; } /* ... */}
[不] std :: exit
這不執(zhí)行任何類型的堆棧展開,并且堆棧上沒有活動(dòng)對(duì)象將調(diào)用其各自的析構(gòu)函數(shù)來執(zhí)行清理。
這在§3.6.1/ 4 [basic.start.init]中強(qiáng)制執(zhí)行:
在不離開當(dāng)前塊的情況下終止程序(例如,通過調(diào)用函數(shù)std :: exit(int)(18.5))不會(huì)銷毀具有自動(dòng)存儲(chǔ)持續(xù)時(shí)間的任何對(duì)象(12.4)。如果在銷毀具有靜態(tài)或線程存儲(chǔ)持續(xù)時(shí)間的對(duì)象期間調(diào)用std :: exit來結(jié)束程序,則程序具有未定義的行為。
現(xiàn)在想一想,你為什么要做這樣的事情?你痛苦地?fù)p壞了多少件物品?
其他[作為壞]替代品
還有其他方法可以終止程序(崩潰除外),但不推薦使用它們。只是為了澄清它們將在這里展示。注意正常的程序終止 并不意味著堆棧展開,而是指操作系統(tǒng)的正常狀態(tài)。
std::_Exit
導(dǎo)致正常的程序終止,就是這樣。std::quick_exit
導(dǎo)致正常的程序終止并調(diào)用std::at_quick_exit
處理程序,不執(zhí)行其他清理。std::exit
導(dǎo)致正常的程序終止,然后調(diào)用std::atexit
處理程序。執(zhí)行其他類型的清理,例如調(diào)用靜態(tài)對(duì)象析構(gòu)函數(shù)。std::abort
導(dǎo)致程序異常終止,不執(zhí)行清理。如果程序以非常非常意外的方式終止,則應(yīng)調(diào)用此方法。除了向操作系統(tǒng)發(fā)出異常終止信號(hào)外,它什么都不做。在這種情況下,某些系統(tǒng)會(huì)執(zhí)行核心轉(zhuǎn)儲(chǔ)。std::terminate
默認(rèn)情況下調(diào)用std::terminate_handler
哪些調(diào)用std::abort
。

TA貢獻(xiàn)1801條經(jīng)驗(yàn) 獲得超8個(gè)贊
要打破條件,請(qǐng)使用return(0);
所以,在你的情況下,它將是:
if(x==1) { return 0; }

TA貢獻(xiàn)1862條經(jīng)驗(yàn) 獲得超7個(gè)贊
如果你的if語句在循環(huán)中你可以使用
break;
如果你想逃避一些代碼并繼續(xù)循環(huán)使用:
繼續(xù);
如果你的if語句不在循環(huán)中你可以使用:
return 0;Or exit();
- 3 回答
- 0 關(guān)注
- 684 瀏覽
添加回答
舉報(bào)