C ++异常:抛出std :: string
时间:2020-03-06 14:44:02 来源:igfitidea点击:
当我的C ++方法遇到奇怪的东西并且无法恢复时,我想抛出一个异常。可以抛出一个std :: string指针吗?
这是我期待做的事情:
void Foo::Bar() { if(!QueryPerformanceTimer(&m_baz)) { throw new std::string("it's the end of the world!"); } } void Foo::Caller() { try { this->Bar(); // should throw } catch(std::string *caught) { // not quite sure the syntax is OK here... std::cout << "Got " << caught << std::endl; } }
解决方案
它有效,但是如果我是你,我不会这样做。完成后,我们似乎并没有删除该堆数据,这意味着我们已经创建了内存泄漏。 C ++编译器负责确保即使弹出堆栈时异常数据也保持活动状态,因此不必觉得我们需要使用堆。
顺便说一句,抛出std :: string
并不是开始的最佳方法。如果使用简单的包装器对象,那么我们将获得更大的灵活性。它可能暂时只是封装一个"字符串",但是将来可能我们会希望包含其他信息,例如导致异常的某些数据或者行号(非常常见)。我们不想在代码库的每个位置上更改所有异常处理,因此,现在就走高路,不要抛出原始对象。
一些原则:
- 我们有一个std :: exception基类,则应该从中派生异常。这样,通用异常处理程序仍然具有一些信息。
- 不要抛出指针而是对象,那样可以为我们处理内存。
例子:
struct MyException : public std::exception { std::string s; MyException(std::string ss) : s(ss) {} ~MyException() throw () {} // Updated const char* what() const throw() { return s.c_str(); } };
然后在代码中使用它:
void Foo::Bar(){ if(!QueryPerformanceTimer(&m_baz)){ throw MyException("it's the end of the world!"); } } void Foo::Caller(){ try{ this->Bar();// should throw }catch(MyException& caught){ std::cout<<"Got "<<caught.what()<<std::endl; } }
所有这些工作:
#include <iostream> using namespace std; //Good, because manual memory management isn't needed and this uses //less heap memory (or no heap memory) so this is safer if //used in a low memory situation void f() { throw string("foo"); } //Valid, but avoid manual memory management if there's no reason to use it void g() { throw new string("foo"); } //Best. Just a pointer to a string literal, so no allocation is needed, //saving on cleanup, and removing a chance for an allocation to fail. void h() { throw "foo"; } int main() { try { f(); } catch (string s) { cout << s << endl; } try { g(); } catch (string* s) { cout << *s << endl; delete s; } try { h(); } catch (const char* s) { cout << s << endl; } return 0; }
我们应该更喜欢h而不是f到g。请注意,在最不推荐使用的选项中,我们需要显式释放内存。
是的。 std :: exception是C ++标准库中的基本异常类。我们可能要避免将字符串用作异常类,因为它们本身在使用过程中会引发异常。如果发生这种情况,那么我们将在哪里?
boost具有出色的样式,可以很好地处理异常和错误。值得一读。
除了可能抛出从std :: exception派生的东西外,我们还应该抛出匿名临时对象并按引用进行捕获:
void Foo::Bar(){ if(!QueryPerformanceTimer(&m_baz)){ throw std::string("it's the end of the world!"); } } void Foo:Caller(){ try{ this->Bar();// should throw }catch(std::string& caught){ // not quite sure the syntax is ok here... std::cout<<"Got "<<caught<<std::endl; } }
- 我们应该抛出匿名临时对象,以便编译器处理所抛出对象的对象生存期-如果我们从堆中抛出新内容,则其他人需要释放该东西。
- 我们应该捕获引用以防止对象切片
。
有关详细信息,请参见Meyer的" Effective C ++第三版",或者访问https://www.securecoding.cert.org/.../ERR02-A.+Throw+anonymous+temporaries+and+catch+by+reference