spr*_*aff 4 c++ constructor exception-handling exception std
建议您始终抛出从中派生的东西,std::exception并且有一些预定义的特化,例如std::runtime_error
std::exception的界面是根据非投掷访问器给出的.大.现在看一下构造函数std::runtime_error
class runtime_error : public exception {
public:
explicit runtime_error (const string &);
};
Run Code Online (Sandbox Code Playgroud)
所以,如果我做这
try {
foo ();
}
catch (...) {
throw std :: runtime_error ("bang");
}
Run Code Online (Sandbox Code Playgroud)
完全有可能foo抛出因为内存不足,在这种情况下构造string参数runtime_error也可以抛出.这将是一个throw-expression,它本身也会抛出:这不会叫std::terminate吗?
这是不是意味着我们应该总是这样做:
namespace {
const std :: string BANG ("bang");
}
...
try {
foo ();
}
catch (...) {
throw std :: runtime_error (BANG);
}
Run Code Online (Sandbox Code Playgroud)
但等等,这也行不通,是吗?因为runtime_error要复制它的论点,这也可能会引发......
...所以这是不是意味着没有安全的方法来使用标准的特化std::exception,并且你应该总是滚动你自己的字符串类,其构造函数只会失败而不抛出?
还是有一些我不知道的伎俩?
我认为您的主要问题是您正在进行catch(...)并转换为std::runtime_error从而丢失原始异常中的所有类型信息.你应该重新考虑一下throw().
实际上,如果你缺乏记忆力,你可能会bad_alloc在某个时刻抛出异常,而且你可以 - 或者应该 - 做的事情也不多.如果由于分配失败以外的原因而要抛出异常,那么构建具有有意义的上下文信息的合理异常对象可能不会有问题.如果在格式化异常对象时遇到内存问题,那么除了传播内存错误之外,您可以做很多事情.
如果你构造一个新的字符串对象来构造一个异常,那么你是对的,但是如果你想用上下文格式化一个消息,这通常是无法避免的.请注意,标准异常对象都有一个const char*构造函数(截至上周),因此如果您有一个const char*想要使用的构造函数,则不必构造新std::string对象.
std::runtime_error必须复制它的参数,但不一定是新的字符串对象.可能存在一个静态分配的内存区域,它可以将其参数的内容包含在内.它只需要满足what()只需要返回a 的要求const char *,它不需要存储std::string对象.