在另一篇文章<《深入理解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;
}