本文主要是介绍noexcept 关键字,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
noexcept 的基本语法
noexcept 是
C++11 为了替代 throw() 而提出的一个新的关键字,在
C++ 中使用函数异常声明列表来查看函数可能抛出的异常。比如:
void func() throw (int,double);
上例就是一个函数异常声明列表,该声明指出 func 可能抛出int和 double 类型的异常。但是在实际编程中很少使用这种写法,所以这一特性在 C++11 中被抛弃。另外,如果异常声明列表写成如下形式:
void func() throw();
这种写法表示函数 func 不抛出任何异常,而这种写法在 c++11 中被新的关键字 noexcept 异常声明所取代。
语法上 noexcept 修饰符有两种形式,一种就是简单地在函数声明后加上 noexcept 关键字。比如:
void func() noecept;
另外一种形式则是接受一个常量表达式(参阅《常量表达式》)作为参数,如下所示:
void func() noexcept(常量表达式);
常量表达式的结果会被转换成一个 bool 类型的值,该值为 true,表示函数不会抛出异常,反之则可能抛出异常。而不带常量表达式的 noexcept
相当于声明了 noexcept(true),即不会抛出异常。
noexcept 的使用
noexcept 可以用来阻止异常的传播和扩散,请看下面的例子:
#include
using namespace
std;
void Throw(){throw
1;}
void NoBlockThrow()
{ Throw(); }
void BlockThrow()
noexcept{ Throw(); }
int main(){
try {
Throw();
}
catch(…) {
cout << “Found throw.”
<< endl; // Found throw
}
try {
NoBlockThrow();
}
catch(…) {
cout << “Throw is not
blocked” <<endl;
}
try {
BlockThrow();
}
catch(…) {
cout << “Found throw
1” << endl;
}
}
在上面的例子中,我们定义了 Throw 函数,该函数的唯一作用是抛出一个异常。而 NoBlackThrow 则是一个 noexcept 修饰的函数。
接着,我们再来看一下上面示例的输出结果:
Found throw.
Throw is not
blocked
terminate called
after throwing an instance of ‘int’
然后我们分析运行结果可以得到这样的结论:NoBlockThrow
会让Throw 函数抛出的异常继续抛出,直到 mian 中的
catch 语句将其捕捉。而 BlockThrow 则会直接调用 std::terminate 中断程序的执行从而阻止了异常的继续传播。
注解:std::terminate 用来强制终止进程
而当
noexcept 作用于模板时,则增强了 c++ 的泛型编程的能力。例如:
template
void fun() noexcept(noexcept(T()))
{}
上面的模板函数会根据条件实现 noexcept 的修饰版本或者无 noexcept 修饰的版本。fun 函数是否是一个 noexcept 的函数,将由 T() 表达式是否会抛出异常所决定,当第二个 noexcept 参数是一个有可能抛出异常的表达式的时候,其返回值为 false ,这时就实现了无 noexcept 修饰的版本,反之,则是实现了 noexcept 修饰的版本。
noexcept 析构函数中的应用
noexcept 更大的用处就是保证程序的安全。因此出于安全考虑,C++11 标准中类的析构函数默认为 noexcept(true)。但是,如果程序员显式地为析构函数指定了
noexcept(false) 或者类的基类或成员有 noexcept(false) 的析构函数,析构函数就不会再保持默认值。
请看下面具体的例子:
#include
using namespace
std;
class People {
public:
~People() { throw 1;} // warning: throw
will always call terminate()
};
class Student {
public:
~Student() noexcept(false) {throw 2;}
};
class Singer {
public:
Student St;
};
int funP() { People
p; }
int funSt() {
Student st; }
int funSi() {
Singer si; }
int main(){
try{
funSt();
}
catch(…){
cout << “caught funSt.”
<< endl;
}
try {
funSi();
}
catch(…) {
cout << “caught funSi.”
<< endl;
}
try {
funP();
}
catch(…){
cout << “caught funP”
<< endl;
}
}
输出结果:
caught funSt.
caught funSi.
terminate called
after throwing an instance of 'int’
在上面的例子中,无论使析构函数声明为 noexcept(false) 的类 Student 还是包含了 Student 类型成员的类 Singer,它们的析构函数都是可以抛出异常的。只有什么都没有声明的类 People 的析构函数默认为 noexcept(true),因此阻止了异常的扩散。
这篇关于noexcept 关键字的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!