为什么std::runtime_error::what()
返回的是const char*
而不是std::string const&
? 在许多情况下,对嵌入字符串的引用的直接返回将会很方便,并且可以避免一些开销。那么不返回的理由是什么?首先是对内部字符串的const引用,而不提供重载函数?我想它与字符串ctor一起能够抛出异常,但我没有看到返回字符串引用的风险。为什么std :: runtime_error :: what()返回const char *而不是std :: string const&
回答
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
继承)。
不一定是嵌入std::string
。成员函数what
是虚拟的,即它被设计为被覆盖。忽略它的主要原因是以其他方式提供字符串,而不是通过std::runtime_error
(无论机制是什么,最可能是存储的std::string
)使用的机制。
好点,有人可能会说char是更一般的。我看了一下在内部使用一个字符串的gcc stl实现''class runtime_error:public exception {string} _M_msg;''并且有点被误导了。 – Martin 2012-07-21 17:47:44
虽然runtime_error确实将std :: string作为参数,所以它可以保留它并按照您的建议返回它,what()方法从std :: exception继承,所以更一般。
由于堆栈展开,抛出异常的开销很可能已经很高,因此您不应该担心这种额外的额外开销。
你很对,开销显然可以忽略不计。我更感兴趣的原因是为什么不采取直接的方式作为你的继承点 – Martin 2012-07-21 17:55:17
- 1. std :: string gets(char *)而不是(const char *)
- 2. “std :: string const”与“const std :: string”
- 3. GCC 4.9 std :: string const char *
- 4. 函数重载为const char *,const char(&)[N]和std :: string
- 5. 为什么std :: string的const访问器返回一个引用?
- 6. C++比较为const char *到的std :: string
- 7. 无法将'std :: string'转换为'const char *
- 8. 返回char数组而不是const char *
- 9. C++,为什么使用const std :: string&parameterName?
- 10. 转换为const char **的为std :: vector的<std::string>
- 11. 为什么cStringUsingEncoding:返回const char *而不是char *?
- 12. 不能从'const char *'转换为'char *'为std :: string :: c_str
- 13. 如何在std :: string中存储const char * []?
- 14. 如何在std :: string中存储const char *?
- 15. std :: string与静态const的char数组
- 16. 为什么GCC接受std :: strrchr()返回的值从'const char *'转换为'char *'?
- 17. 从函数返回const char *的正确方法,例如覆盖std :: exception :: what()
- 18. 从std :: string中提取const char而不复制?
- 19. 哪一个使用const char []或const std :: string?
- 20. 从const char * +长度构造一个const std :: string便宜吗?
- 21. 不能将'std :: string {aka std :: basic_string}'转换为'const char *'参数'1'到'int system(const char *)
- 22. 从“std :: istringstream”初始化“const std :: string”
- 23. 运算符std :: string()const?
- 24. C++ const std :: string赋值
- 25. 不能超载的std :: string常量和函数为const char *
- 26. 无法将'const char *'转换为'std :: istream *
- 27. 数据去变换为const char *时的std :: string
- 28. “const std :: string&msg”什么,如何以及为什么? C++
- 29. 我应该返回gsl :: span <const T>而不是const std :: vector <T>&
- 30. 从内部使用静态std :: string的函数返回const char *是否安全?
-1截至本评论时,答案中的代码将不会编译,即它不正确。如果存在'std :: string',则不会保证措辞“可能返回'std :: string'”,即不正确。抛出“什么”会引入“一次抛出两个异常”的说法是不正确的:在处理程序中调用了什么。一次抛出两个异常的注释在技术上是不正确的:在堆栈展开期间,可以执行try块,允许嵌套异常抛出。但这似乎只是模糊的措辞。 – 2012-07-21 18:18:18
好的,我修正了代码,并重新说明了抛出第二个异常的说明,以使它更清楚(我希望)。正如Alf所说,异常可以在try块中抛出。 – stativ 2012-07-22 07:22:22
现在,代码将被编译,但如果使用会导致未定义的行为(它会返回一个指向临时的指针)。三个不正确的技术索赔仍然存在。这个答案仍然没有回答OP的问题,“为什么”,即有很多不正确的说法,还有无意义的UB代码,而且没有答案。 – 2012-07-22 12:07:35