2012-07-21 150 views
2

爲什麼std::runtime_error::what()返回的是const char*而不是std::string const&? 在許多情況下,對嵌入字符串的引用的直接返回將會很方便,並且可以避免一些開銷。那麼不返回的理由是什麼?首先是對內部字符串的const引用,而不提供重載函數?我想它與字符串ctor一起能夠拋出異常,但我沒有看到返回字符串引用的風險。爲什麼std :: runtime_error :: what()返回const char *而不是std :: string const&

回答

4

std::runtime_error繼承自std::exception它定義了virtual const char* what() const throw();,所以最簡單的回答是它是函數的重載,並且您可以確定任何標準異常都以這種方式定義它。它可能(取決於實現)返回std::string,但它會與標準庫的其餘部分不一致。

我認爲what()返回const char*的原因是,您可以避免任何可能失敗的操作(特別是可能會引發異常)。考慮下面的代碼,不應該在下面的代碼的std::string分配可能會失敗,失敗

virtual const char* what() const throw() { 
    return "An error has occured"; 
} 

然而,拋出一個異常:

std::string what() const throw() { 
    return std::string("An error has occured"); 
} 

如果字符串的構造扔在這裏,應用程序將無論如何,最有可能崩潰,因爲該函數指定throw()

在異常中使用std::string引入了分配不可能的內存的需要(注意,std::bad_alloc也從std::exception繼承)。

+0

-1截至本評論時,答案中的代碼將不會編譯,即它不正確。如果存在'std :: string',則不會保證措辭「可能返回'std :: string'」,即不正確。拋出「什麼」會引入「一次拋出兩個異常」的說法是不正確的:在處理程序中調用了什麼。一次拋出兩個異常的註釋在技術上是不正確的:在堆棧展開期間,可以執行try塊,允許嵌套異常拋出。但這似乎只是模糊的措辭。 – 2012-07-21 18:18:18

+0

好的,我修正了代碼,並重新說明了拋出第二個異常的說明,以使它更清楚(我希望)。正如Alf所說,異常可以在try塊中拋出。 – stativ 2012-07-22 07:22:22

+0

現在,代碼將被編譯,但如果使用會導致未定義的行爲(它會返回一個指向臨時的指針)。三個不正確的技術索賠仍然存在。這個答案仍然沒有回答OP的問題,「爲什麼」,即有很多不正確的說法,還有無意義的UB代碼,而且沒有答案。 – 2012-07-22 12:07:35

4

不一定是嵌入std::string。成員函數what是虛擬的,即它被設計爲被覆蓋。忽略它的主要原因是以其他方式提供字符串,而不是通過std::runtime_error(無論機制是什麼,最可能是存儲的std::string)使用的機制。

+0

好點,有人可能會說char是更一般的。我看了一下在內部使用一個字符串的gcc stl實現''class runtime_error:public exception {string} _M_msg;''並且有點被誤導了。 – Martin 2012-07-21 17:47:44

1

雖然runtime_error確實將std :: string作爲參數,所以它可以保留它並按照您的建議返回它,what()方法從std :: exception繼承,所以更一般。

由於堆棧展開,拋出異常的開銷很可能已經很高,因此您不應該擔心這種額外的額外開銷。

+0

你很對,開銷顯然可以忽略不計。我更感興趣的原因是爲什麼不採取直接的方式作爲你的繼承點 – Martin 2012-07-21 17:55:17

相關問題