现在的位置: 首页 > 综合 > 正文

了解C++11(五)—— noexcept

2014年09月02日 ⁄ 综合 ⁄ 共 1438字 ⁄ 字号 评论关闭

在c++11标准之前,c++在函数声明中有exception specification(异常声明)的功能,用来指定函数可能抛出的异常类型。

voidFunc0() throw(runtime_error);
voidFunc1() throw();
voidFunc2();

函数Func0可能抛出runtime_error类型的异常;函数Func1不会抛出任何异常;函数Func2没有异常说明,则该函数可以抛出任何类型的异常。

如果函数抛出了没有在异常说明中列出的异常,则编译器会调用标准库函数unexpected。默认情况下,unexpected函数会调用terminate函数终止程序。

这种异常声明的功能很少使用,因此在c++11中被弃用。c++11引入noexcept,具体用法如下。

voidFunc3() noexcept;

noexcept的功能相当于上面的throw(),表示函数不会抛出异常。如果noexcept修饰的函数抛出了异常,编译器可以选择直接调用std::terminate()终止程序运行。noexcept比throw()效率高一些。

voidFunc4() noexcept(常量表达式);

如果常量表达式的结果为true,表示该函数不会抛出异常,反之则有可能抛出异常。不带常量表达式的noexcept相当于noexcept(true)。

上面noexcept的用法是其作为修饰符时的用法,实际上noexcept还可以作为操作符,常用于模板中。

template <typename T>
voidfunc5() noexcept( noexcept(T()) ) {}

第2个noexcept就是一个操作符,如果其参数是一个有可能抛出异常的表达式,则返回值为false(func5为noexcept(false),有可能会抛出异常),否则返回值为true(func5为noexcept(true),不会抛出异常)。

这样函数是否会抛出异常,可以由表达式进行推导,使得c++11更好的支持泛型编程。

noexcept被大量的使用在c++11的标准库中,用于提高标准库的性能,以及满足一些阻止异常扩散的需求。随便在c++11标准文档中搜索一下noexcept关键字,就知道它的应用有多广泛了。

c++11默认将delete设置成noexcept,这样可以提高应用程序的安全性,因为在析构函数中不应该抛出异常,而析构函数中经常会调用delete。

voidoperator delete(void* ptr) noexcept;
voidoperator delete(void* ptr, const std::nothrow_t&) noexcept;
 
voidoperator delete[](void* ptr) noexcept;
voidoperator delete[](void* ptr, const std::nothrow_t&) noexcept;
 
voidoperator delete(void* ptr, void*) noexcept;
voidoperator delete[](void* ptr, void*) noexcept;

同样出于安全因素考虑,c++11将类的析构函数默认为noexcept(true)。但如果程序员显示的为析构函数指定noexcept(false),或者类的基类或成员有noexcept(false)的析构函数,则析构函数不会再保持默认值。

学习资料: 《深入理解c++11》《c++ primer》

抱歉!评论已关闭.