我无法理解noexceptC++ 11/14中in关键字的用法和用途.我的意思是它是那些不发射的功能的签名exceptions.但它真的有效吗?
请看下面的代码:
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
void seev (vector<int> &v) noexcept;
void seev (vector<int> &v) noexcept
{
for (int i=0;i<10;++i)
{
cout<<v.at(i)<<' ';
}
}
int main()
{
vector<int> v {1,2,3,4,5};
seev(v);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
上面的代码肯定会抛出一个out_of_range exception.所以noexcept这里的使用是没用的,或者是吗?
我的疑问是:
noexcept工作怎么样?
怎么用?
什么throw()不能做到这noexcept一点?
Val*_*lus 11
函数的noexcept规范仅仅是程序员通知编译器函数是否应该抛出异常的方法.
编译器可以使用此信息对非抛出函数启用某些优化,并启用noexcept运算符,该运算符可以在编译时检查是否声明了特定表达式抛出任何异常.
例如,如果元素的移动构造函数是noexcept,则std :: vector等容器将移动它们的元素,否则复制(除非复制构造函数不可访问,但是可能抛出的移动构造函数,在这种情况下强大的异常保证)被免除).
noexcept是throw()的改进版本,在C++ 11中已弃用.与throw()不同,noexcept不会调用std :: unexpected并且可能会或可能不会展开堆栈,这可能允许编译器在没有throw()的运行时开销的情况下实现noexcept.
有关详细信息,请访问以下网站
编辑:示例源代码以说明上述要点.
// whether foo is declared noexcept depends on if the expression
// T() will throw any exceptions, check in compile time
template <class T>
void foo() noexcept(noexcept(T())) {
}
void bar() noexcept(true) {
}
void baz() noexcept {
throw 42;
} // noexcept is the same as noexcept(true)
int main()
{
foo<int>(); // noexcept(noexcept(int())) => noexcept(true), so this is fine
bar(); // fine
baz(); // compiles, but at runtime this calls std::terminate
}
Run Code Online (Sandbox Code Playgroud)
noexcept表示函数不是为了抛出异常,而是作为开发人员提供的保证,而不是由编译器强制执行.因此,在函数调用可能抛出异常的函数的情况下使用它是不好的.
throw()删除了整个范围的说明符,因为异常说明符在C++中不是最优的,请参阅:C++ 03之间的差异throw()说明符C++ 11 noexcept
noexcept具有不说明抛出哪个异常的优点,而是抛出是否抛出异常.它接受一个参数,false如果您希望函数抛出异常,则可以使用该参数.
对此的使用可以是例如继承的类结构,其中一个超类希望"强制"到继承的类,不允许特定的虚函数抛出异常.此外,编译器可以使用该信息进行优化.
noexcept 也是一个运算符,可以根据第5.3.7节评估表达式并返回该表达式是否可以抛出异常.
5.3.7 noexcept运算符[expr.unary.noexcept]
1 noexcept运算符确定对其操作数(即未评估的操作数(第5条))的求值是否可以抛出异常(15.1).noexcept-expression:noexcept(expression)
2 noexcept运算符的结果是bool类型的常量,是一个rvalue.
3如果在表达式包含的潜在评估上下文中,则noexcept运算符的结果为false
- 对函数,成员函数,函数指针或成员函数指针的潜在评估调用,它没有非抛出异常规范(15.4),除非调用是常量表达式(5.19),
- 可能 -计算throw-expression(15.1),
- 一个潜在评估的dynamic_cast表达式dynamic_cast(v),其中T是一个引用类型,需要运行时检查(5.2.7),或者
- 一个可能被评估的typeid表达式(5.2) .8)应用于glvalue表达式,其类型是多态类类型(10.3).
否则,结果是真的.
我无法解释可能的优化以及Scott Meyers:http://aristeia.com/EC++11-14/noexcept%202014-03-31.pdf来自他的博客文章:尽可能声明函数noexcept?
展开调用堆栈和可能展开调用堆栈之间的区别对代码生成产生了惊人的巨大影响.在noexcept函数中,如果异常将从函数传播出来,优化器不需要将运行时堆栈保持在不可解除的状态,也不必确保如果异常离开函数,则以构造的逆序销毁noexcept函数中的对象. .结果是更多的优化机会,不仅在noexcept函数的主体内,而且在调用函数的站点.这种灵活性仅适用于noexcept功能.具有"throw()"异常规范的函数缺少它,没有异常规范的函数也没有.
我发布了两段代码来解释你的问题:
代码1:
#include <iostream>
using namespace std;
void foo() noexcept // see the noexcept specifier
{
throw 42;
}
int main()
{
try
{
foo();
}
catch(...)
{
cerr<<"exception caught\n";
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这里的输出将是: -
terminate called after throwing an instance of 'int'
This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
Run Code Online (Sandbox Code Playgroud)
如果我删除了noexcept那么:
代码2:
#include <iostream>
using namespace std;
void foo() // noexcept is eliminated
{
throw 42;
}
int main()
{
try
{
foo();
}
catch(...)
{
cerr<<"exception caught\n";
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出将是: -
exception caught
Run Code Online (Sandbox Code Playgroud)
因为foo签了noexcept,因此terminate被称为.
继承构造函数和隐式声明的默认构造函数,拷贝构造函数,移动构造函数,析构函数,拷贝赋值运算符,和移动赋值操作符都是noexcept(true)在默认情况下,除非他们需要调用一个函数是noexcept(false),在这种情况下,这些功能是noexcept(false).
你也可以写下这样的行:
cout << boolalpha << noexcept(foo); // here noexcept acts as
// an operator instead of a specifier
Run Code Online (Sandbox Code Playgroud)
以上行将检查是否foo会抛出exception.如果它会抛出那么返回值将是trueelse false.
您可以在此阅读更多有关这些:http://scottmeyers.blogspot.dk/2014/03/declare-functions-noexcept-whenever.html
| 归档时间: |
|
| 查看次数: |
7908 次 |
| 最近记录: |