《深入理解C++11》笔记--noexcept

在另一篇文章<《深入理解C++11》笔记–扩展>中写到过noexcept运算符相关的内容,因为noexcept涉及到的内容较多,单独写一篇文章进行详细介绍。

noexcept修饰符
noexcept可以用来修饰函数,在函数的后面加上noexcept,代表这个函数不会抛出异常,如果抛出异常程序就会终止。这个特性在C++11中出现很多,主要是为了当程序不该出现异常的地方抛出异常时终止程序,例如delete函数、析构函数默认都是noexcept。

void my_exception()
{
    throw 1;
}
void my_exception_noexcept() noexcept
{
    throw 1;
}

void my_exception_noexcept_false() noexcept(false)
{
    throw 1;
}

int main()
{
    try {
        my_exception();
    } catch (...) {
        std::cout << "throw" << std::endl;  // throw
    }

    try {
        my_exception_noexcept();            // terminate
    } catch (...) {
        std::cout << "throw" << std::endl;  

    try {
        my_exception_noexcept_false(); 
    } catch (...) {
        std::cout << "throw" << std::endl;   // throw
    }

    return 0;
}

上面的代码最终会输出throw,如果在函数my_exception后加上noexcept,void my_exception() noexcept,程序就会直接退出。noexcept还能加上常量表达式参数,例如noexcept(true),当常量表达式结果为true时,标识该函数不能抛出异常,否则能够抛出异常。noexcept不带参数时默认为true。

noexcept运算符
noexcept还能作为运算符noexcept(expression),noexcept 运算符不对 expression 求值。若 expression 含有至少一个下列潜在求值的构造则结果为 false :
1、调用无不抛出异常指定的任意类型函数,除非它是常量表达式。
2、throw 表达式。
3、目标类型是引用类型,且转换时需要运行时检查的 dynamic_cast 表达式
4、参数类型是多态类类型的 typeid 表达式
5、所有其他情况下结果是 true 。

void test() {}
void test_noexcept() noexcept(true) {}
void test_noexcept_false() noexcept(false) {  }

class Base{
public:
    virtual void f() {}
};
class Test :public Base {
};

int main(int argc, char **argv)
{
    std::cout << noexcept(test()) << std::endl;                       \\ false
    std::cout << noexcept(test_noexcept()) << std::endl;              \\ false
    std::cout << noexcept(test_noexcept_false()) << std::endl;        \\ true
    std::cout << noexcept(throw) << std::endl;                        \\ false

    Test test;
    Base& base = test;
    std::cout << noexcept(dynamic_cast<Test&>(base)) << std::endl;     \\ false
    std::cout << noexcept(typeid(base)) << std::endl;                  \\ false

    return 0;
}

另外noexcept运算符能用于模板,这样函数是否noexcept可以自定义,例如一下示例,定义了fun,其中第一个noexcept是修饰符,第二个为运算符,对模板参数T进行运算。

template <typename T>
void fun() noexcept(noexcept(T())) { throw 1; }

class Base {
public:
    virtual void f() {}
};
class Test :public Base {
public:
    ~Test() noexcept(true) {}
};
class TestFalse :public Base {
public:
    ~TestFalse() noexcept(false) {}
};

int main(int argc, char **argv)
{
    std::cout << noexcept(TestFalse()) << std::endl;         // false
    std::cout << noexcept(Test()) << std::endl;              // true

    try
    {
        fun<TestFalse>();
    }
    catch (...)
    {
        std::cout << "throw" << std::endl;                    // throw
    }

    try
    {
        fun<Test>();                                          // terminate
    }
    catch (...)
    {
        std::cout << "throw" << std::endl;
    }

    getchar();
    return 0;
}

猜你喜欢

转载自blog.csdn.net/wizardtoh/article/details/80579131