2012-07-21 152 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

相关问题