在C++标准中,有以下定义:
template <class T, size_t N> void swap(T (&a)[N], T (&b)[N])
noexcept(noexcept(swap(*a, *b)));
Run Code Online (Sandbox Code Playgroud)
怎么noexcept(noexcept(swap(*a, *b)))办?
我对析构函数有点困惑noexcept.我的理解是,在C++ 11中,任何析构函数(包括用户定义的)都是隐含的noexcept(true),即使我们throw来自它.并且必须明确指定noexcept(false)他们是否因某种原因希望它是那样的.
我所看到的恰恰相反 - 与GCC 4.7.2一样,用户定义的析构函数,无论类和析构函数多么原始,都是隐含的noexcept(false).我在这里错过了什么?是否有一些隐藏的问题与用户定义的析构函数?
我看到C++ 11添加了noexcept关键字.但我真的不明白它为什么有用.
如果函数在不应该抛出时抛出 - 为什么我希望程序崩溃?
那么什么时候应该使用它?
此外,它将如何与/ Eha和使用编译一起工作_set_se_translator?这意味着任何代码行都会抛出c ++异常 - 因为它可能抛出一个SEH异常(因为访问受保护的内存)并且它将被转换为c ++异常.
那会发生什么?
根据this question的答案,可以noexcept在某些条件下定义默认移动构造函数。例如,下面的类生成一个noexcept移动构造函数:
class C {};
Run Code Online (Sandbox Code Playgroud)
根据对这个问题的回答,使用说明= default符定义的移动构造函数将生成与隐式定义的移动构造函数相同的构造函数。所以,如果我正确理解它,下面的类应该生成一个noexcept移动构造函数:
class D {
D(D&&) = default;
};
Run Code Online (Sandbox Code Playgroud)
要检查,我使用的std::is_nothrow_move_constructible功能,看是否C和D有一个noexcept移动构造函数:
#include <type_traits>
int main() {
static_assert(std::is_nothrow_move_constructible<C>::value, "C should be noexcept MoveConstructible");
static_assert(std::is_nothrow_move_constructible<D>::value, "D should be noexcept MoveConstructible");
return 0;
}
Run Code Online (Sandbox Code Playgroud)
当我编译时,我收到此错误:
$ g++ toy.cpp -o toy
toy.cpp: In function ‘int main()’:
toy.cpp:16:5: error: static assertion failed: D should be noexcept MoveConstructible
static_assert(std::is_nothrow_move_constructible<D>::value, "D should be …Run Code Online (Sandbox Code Playgroud) 我听说noexcept关键字更像是'它永远不应该抛出异常',而不是'它没有'.
我不认为使用noexcept关键字是好的,如果我不确定它是否会抛出异常,但noexcept关键字有时与移动构造函数中的性能有关.
所以我尝试使用noexcept限定符,但如果它在定义中有多个语句就变得更难,它变成了一种复制和粘贴的东西.
template <class T>
void f(T&& t)
noexcept(noexcept(statement_1) &&
noexcept(statement_2) &&
noexcept(statement_3) &&
noexcept(statement_4) &&
noexcept(statement_5))
{
statement_1;
statement_2;
statement_3;
statement_4;
statement_5;
}
Run Code Online (Sandbox Code Playgroud)
我认为编译器可以判断一个函数的定义是否包含非抛出语句,因此noexcept如果有一个类似的表达式会更容易使用noexcept(auto),但似乎标准中没有这样的东西.
有没有办法简化noexcept表达式?
以下代码在C++中是否有效?
int main() noexcept
{
}
Run Code Online (Sandbox Code Playgroud)
既铛++ 3.8.0和克++ 7.2.0 编译它细(与-std=c++14 -O0 -Wall -Wextra -Werror -pedantic-errors编译标志).
是否允许在函数规范中使用复杂条件(例如包括noexcept运算符)?noexceptmain
那么C++ 17呢?据我所知,noexcept说明符成为本标准修订版中函数类型的一部分.
在C++ 17 noexcept 中已添加到类型系统中:
void r1( void (*f)() noexcept ) { f(); }
void foo() { throw 1; }
int main()
{
r1(foo);
}
Run Code Online (Sandbox Code Playgroud)
C++ 17模式下的最新版本的gcc和clang拒绝该调用,r1(foo)因为void (*)()无法隐式转换为void (*)() noexcept.
但std::function改为:
#include <functional>
void r2( std::function<void() noexcept> f ) { f(); }
void foo() { throw 1; }
int main()
{
r2(foo);
}
Run Code Online (Sandbox Code Playgroud)
clang接受该程序,显然忽略了noexcept说明者; 和g ++给出了一个奇怪的错误g++.
在C++ 17中第二个程序的正确行为是什么?
我无法找到迫使与申报功能标准的东西extern "C"是noexcept,无论是含蓄或明确.
但是,应该很清楚C调用约定不能支持异常......或者是它?
标准是否提到了这个,我错过了某个地方?如果没有,为什么不呢?它只是作为各种实现细节留下的吗?
我有以下代码:
class MyClass
{
static constexpr bool foo() { return true; }
void bar() noexcept(foo()) { }
};
Run Code Online (Sandbox Code Playgroud)
我希望,因为它foo()是一个static constexpr函数,并且因为它是在bar声明之前定义的,所以这是完全可以接受的.
但是,g++给我以下错误:
error: ‘static constexpr bool MyClass::foo()’ called in a constant expression
Run Code Online (Sandbox Code Playgroud)
这是......不太有用,因为在常量表达式中调用函数的能力是整个点constexpr.
clang++更有帮助.除了声明参数noexcept必须是常量表达式的错误消息之外,它还说:
note: undefined function 'foo' cannot be used in a constant expression
note: declared here
static constexpr bool foo() { return true; }
^
Run Code Online (Sandbox Code Playgroud)
那么......这是一个两遍编译问题吗?问题是编译器在定义任何成员函数之前是否尝试声明它们中的所有成员函数?(注意,在类的上下文之外,编译器都不会抛出错误.)这让我感到惊讶; 直观地说,我认为static constexpr成员函数不能在任何和所有常量表达式中使用,无论是在类中还是在类中.
请参考以下示例代码:
void test(const Item& item = Item()) {
...
}
Run Code Online (Sandbox Code Playgroud)
假设,一旦item传递给函数,就不能抛出.
问题是:应该标记功能noexcept还是noexcept(noexcept(Item()))?
IHMO,前者应该没事,但我不确定.非常感谢标准的报价!