zoukankan      html  css  js  c++  java
  • 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.

    顺序 选择 循环 总结

  • 相关阅读:
    一行Haskell语句打印勾股数
    给孩子增加学习生物的兴趣,买了个显微镜
    实现求n个随机数和为sum的haskell程序
    用haskell实现的八皇后程序
    桥牌笔记:第一墩决定成败
    读书笔记:父母离去前要做的55件事
    LINQ to SQL系列三 使用DeferredLoadingEnabled,DataLoadOption指定加载选项
    LINQ to SQL系列四 使用inner join,outer join
    Asp.Net 4.0 新特性 系列 之一 从页面标记<%%>说起
    使用javascript自动标记来自搜索结果页的关键字
  • 原文地址:https://www.cnblogs.com/Braveliu/p/12227239.html
Copyright © 2011-2022 走看看