C++11 noexcept修饰符与noexcept操作符
noexcept修饰符与noexcept操作符
首先,明确一点:
在C++11之后,表示函数不会抛出异常的动态异常声明throw()被新的noexcept异常声明所取代。
在通常情况下,在C++11中使用noexcept可以有效的阻止异常的传播与扩散。
【1】noexcept修饰符
从语法上讲,noexcept修饰符有两种形式:
(1)在函数声明后直接加上关键字noexcept
noexcept形如其名,表示其修饰的函数不会抛出异常。不过与throw()动态异常声明不同的是:
在C++11中如果noexcept修饰的函数结果却抛出了异常,编译器可以选择直接调用std::terminate()函数来终止程序的运行,这比基于异常机制的throw()在效率上会高一些。
这是因为异常机制会带来一些额外开销,比如函数抛出异常,会导致函数栈被依次地展开(unwind),并依帧调用在本帧中已构造的自动变量的析构函数等。
(2)在(1)的关键字后再加一个参数(常量表达式)
若常量表达式转换成bool类型的值为true,说明不会抛出异常;反之,则可能会抛出异常。
其实,回头再看第一种形式,不带常量表达式的noexcept相当于声明了noexcept(true),即不会抛出异常。
以上示例如下:
1 #include <iostream> 2 using namespace std; 3 4 void my_exception() 5 { 6 throw 1; 7 } 8 9 void my_exception_noexcept_false() noexcept(false) 10 { 11 throw 1; 12 } 13 14 void my_exception_noexcept_true() noexcept 15 { 16 throw 1; 17 } 18 19 int main() 20 { 21 try 22 { 23 my_exception(); 24 } 25 catch (...) 26 { 27 cout << "throw my_exception" << endl; // throw my_exception 28 } 29 30 try 31 { 32 my_exception_noexcept_false(); 33 } 34 catch (...) 35 { 36 cout << "throw noexcept_false" << endl; // throw noexcept_false 37 } 38 39 try 40 { 41 // warning C4297 : “my_exception_noexcept_true”: 假定函数不引发异常,但确实发生了 42 my_exception_noexcept_true(); // terminate 43 } 44 catch (...) 45 { 46 cout << "throw noexcept_true " << endl; 47 } 48 }
注意:本地VS2019环境,在编译my_exception_noexcept_true时,报出警告warning C4297:假定函数不引发异常,但确实发生了
【2】noexcept操作符
(1)noexcept作为操作符noexcept(expression),noexcept操作符不对expression求值。
若expression含有至少一个下列潜在求值的构造则结果为false:
[1] 调用没有指定不抛出异常的任意类型函数,除非它是常量表达式。
[2] throw表达式。
[3] 目标类型是引用类型,且转换时需要运行时检查的dynamic_cast表达式。
[4] 参数类型是多态类类型的typeid表达式。
示例如下:
1 #include <iostream> 2 using namespace std; 3 4 void test() { } 5 void test_noexcept() noexcept(true) { } 6 void test_noexcept_false() noexcept(false) { } 7 8 class Base 9 { 10 public: 11 virtual void f() {} 12 }; 13 14 class Test : public Base 15 {}; 16 17 int main(int argc, char** argv) 18 { 19 cout << noexcept(test()) << endl; // false 20 cout << noexcept(test_noexcept()) << endl; // true 21 cout << noexcept(test_noexcept_false()) << endl; // false 22 cout << noexcept(throw) << endl; // false 23 24 Test test; 25 Base& base = test; 26 cout << noexcept(dynamic_cast<Test&>(base)) << endl; // false 27 cout << noexcept(typeid(base)) << endl; // false 28 }
(2)noexcept操作符用于模板。示例如下:
1 template <class T> 2 void fun() noexcept(noexcept(T())) {}
这里,fun函数是否是一个noexcept的函数,将由T()表达式是否会抛出异常所决定。
这里的第二个noexcept就是一个noexcept操作符。
当其参数是一个有可能抛出异常的表达式的时候,其返回值为false,反之为true。
应用示例如下:
1 #include <iostream> 2 using namespace std; 3 4 template <typename T> 5 void fun() noexcept(noexcept(T())) { throw 1; } 6 7 class Base 8 { 9 public: 10 virtual void f() { } 11 }; 12 13 class Test : public Base 14 { 15 public: 16 ~Test() noexcept(true) { } 17 }; 18 19 class TestFalse : public Base 20 { 21 public: 22 ~TestFalse() noexcept(false) { } 23 }; 24 25 int main(int argc, char** argv) 26 { 27 cout << noexcept(TestFalse()) << endl; // false 28 cout << noexcept(Test()) << endl; // true 29 30 try 31 { 32 fun<TestFalse>(); 33 } 34 catch (...) 35 { 36 cout << "throw" << endl; // throw 37 } 38 39 try 40 { 41 fun<Test>(); // terminate 42 } 43 catch (...) 44 { 45 cout << "throw" << endl; 46 } 47 48 getchar(); 49 return 0; 50 }
good good study, day day up.
顺序 选择 循环 总结