5

所以我寫了一些代碼,我注意到,除了語法,類型和其他編譯時錯誤,C++不會拋出任何其他異常。所以我決定用一個非常重要的程序測試了這一點:C++異常處理

#include<iostream> 

int main() { 
    std::count<<5/0<<std::endl; 
return 1 
} 

當我用G ++編譯它,G ++給了我一個警告,說我被劃分爲0但它仍然編譯的代碼。然後當我運行它時,它會打印一些非常大的任意數字。當我想知道的是,C++如何處理異常?應該是一個非常簡單的例子,當拋出異常並且程序應該終止時。

我是否必須將我的整個程序封裝在一個巨大的try塊中,然後捕獲某些異常?我在Python中知道拋出異常時,程序將立即終止並打印出錯誤。 C++是做什麼的?是否有運行時異常停止執行並終止程序?

回答

8

存在運行時異常,但並非所有「錯誤」都會導致運行時異常被拋出。例如,獲取數組越界或解引用空指針就是「未定義行爲」 - 意味着任何事情都可能發生。除零也屬於「未定義」類別。

導致「未定義行爲」而非異常的一些操作的基本原理是效率。假設超出界限的數組訪問需要拋出異常。然後,編譯器必須爲每個數組訪問生成代碼,以檢查它是否超出範圍,如果是,則引發異常。這是很多檢查,其中大部分是不必要的。相反,編譯器所做的只是爲元素訪問生成指令,假設它處於邊界內。如果碰巧出界,則發生任何事情(例如分段故障)。如果你想想要進行檢查,你總是可以明確地編碼。

這使得C++比總是進行檢查的語言(例如Java或python)更強大,因爲您可以選擇何時需要檢查,何時不檢查。 (另一方面,它使C++不如Java或python安全,這是一種折衷)。


至於什麼時候拋出一個異常,但沒有在任何地方陷入發生什麼事,通常編譯器實現將打印包含錯誤信息的異常的what()。在你的例子中,這是不適用的,因爲沒有拋出運行時異常。

+0

謝謝,這是有道理的。另一個問題。如果不是使用std :: cout,我使用std :: cerr,會拋出異常,還是隻打印到錯誤流?如果我創建自己的異常(可以說foo),並且在我的代碼中,我會說throw foo,那麼我的程序是否會立即被殺死,並且foo.what()會被打印出來?還是我必須明確告訴C++這樣做? – user1413793

+0

@ user1413793:如果你寫入'std :: cerr',它只會打印到錯誤流。您可以通過命令行('>'vs'2>')通過重定向將輸出流和錯誤流發送到不同的地方。如果你拋出一個異常,並且你沒有在任何地方捕捉到它,程序將立即終止並打印一條錯誤消息。 (更確切的說,一個名爲'std :: terminate'的函數將被調用,它的默認行爲是終止程序並打印異常的消息。你可以通過調用'std :: set_terminate'來覆蓋行爲。有興趣。) – HighCommander4

0

Visual C++將此標記正確地標記爲零除錯誤。所以如果它不編譯,那麼運行它就沒有問題了。

+0

但它是 「正確」?只是好奇。 –

+0

甚至在任何標準之前,除以零都是未定義的,對嗎? – Superman

3

是的,有運行時異常。一個示例是out_of_range,它由vector::at引發。

然而,除以零是未定義的(C++ 0X§5.6/ 4):

如果/或%所述第二操作數是零的行爲被理解過程音響定義。

因此,它可能無法編譯,拋出一個僞造的異常,打印「一些非常大的任意數字」或段錯誤。

+0

好的,謝謝!我只是困惑,因爲其他語言拋出異常,但這是有道理的:) – user1413793

2

C++只拋出在C++標準中定義明確的標準異常。(是它包括了一些運行時異常

整型除以零不是一個標準C++異常(技術上它是未定義行爲)。所以不會引發隱式異常。一個特定的編譯器可能會將運行時錯誤映射爲某種異常(您需要檢查編譯器文檔中是否有這種情況,有些編譯器映射除以零來表示某種異常),如果是這樣,您可以捕獲該特定異常。但是請注意,這不是可移植的行爲,不適用於所有編譯器。

最好你可以做的是自己檢查錯誤條件(除數等於零),並在這種情況下顯式拋出一個異常。

編輯:要根據標準答案的評論

class A 
{ 
    public: 
     void f() 
     { 
      int x; 
      //For illustration only 
      int a = 0; 
      if(a == 0) 
        throw std::runtime_error("Divide by zero Exception"); 
      x=1/a; 
     } 

     A() 
     { 
       try 
       { 
        f(); 
       } 
       catch(const std::runtime_error& e) 
       { 
        cout << "Exception caught\n"; 
        cout << e.what(); 
       } 
     } 
};  
+0

會拋出異常導致程序終止並打印出異常,或者我必須接着捕捉異常並明確告訴C++該怎麼做? – user1413793

+1

@ user1413793:更新了答案。您必須捕捉異常並決定如何處理。 –