我读到有关过度使用noexcept可能会阻碍可测试库的担忧。
考虑:
T& vector::front() noexcept {
assert(!empty()); // <- this may throw in some test-frameworks
return data[0];
}
Run Code Online (Sandbox Code Playgroud)
使用noexcept编译器的注释可能会优化异常代码,这会/可能会阻止正确处理assert()(或作者想在这里使用的任何函数进行测试)。
因此,我想知道,在库中从不使用无条件,noexcept而是始终将其与 am-I-in-a-test-condition “链接”是否可行。像这样:
#ifdef NDEBUG // asserts disabled
static constexpr bool ndebug = true;
#else // asserts enabled
static constexpr bool ndebug = false;
#end
T& vector::front() noexcept(ndebug) {
assert(!empty());
return data[0];
}
Run Code Online (Sandbox Code Playgroud)
然后也许将它添加为一个宏(虽然,我讨厌那样):
#define NOEXCEPT noexcept(ndebug)
T& vector::front() NOEXCEPT {
assert(!empty());
return data[0];
}
Run Code Online (Sandbox Code Playgroud)
你怎么认为?这有任何意义吗?还是不可行?还是不能解决问题?或者根本没有问题?:-)
我已经阅读了有关 noexcept 说明符和编译器优化的不清楚的内容。指定noexcept编译器时可能会优化:
尝试使用Xcode 6.1中的clang版本(基于LLVM 3.5svn的clang-600.0.54)编译以下代码,-std=c++11并-stdlib=libc++给出一些我不太了解的错误.
#include <functional>
struct Impl
{
typedef std::function<void ()> L;
L l;
int i;
};
struct Hndl
{
Impl* impl;
Hndl(Impl* i): impl(i) {}
~Hndl() noexcept(false) {}
};
int main(int argc, char * argv[]) {
Hndl h(new Impl());
h.impl->l = [=]
{
h.impl->i = 42;
};
return 0;
}
Run Code Online (Sandbox Code Playgroud)
结果:
In file included from t.cpp:1:
/Applications/Xcode-6.1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/functional:1293:52: error: exception specification of overriding
function is more lax than base version
template<class _FD, class _Alloc, class _FB> …Run Code Online (Sandbox Code Playgroud) 举个例子:
double values[] {2.5, -3.5, 4.5, -5.5, 6.5, -7.5};
std::vector<double> squares(std::end(values) - std::begin(values));
std::transform(std::begin(values), std::end(values), std::begin(values), std::begin(squares),
[](double x1, double x2) throw() { return x1 * x2; });
Run Code Online (Sandbox Code Playgroud)
这在功能上是否等同于以下内容?
[](double x1, double x2) noexcept { return x1 * x2; })
Run Code Online (Sandbox Code Playgroud)是否有令人信服的原因,为什么我要用修饰符标记这样的表达式(或类似的基本表达式),或者在这种情况下,最好不要使用它,而不必打扰?
我大量使用noexcept,不幸的是如果一些传递依赖最终导致一个罕见的情况(我们不知道),崩溃是非常难以调试 - 因为被调用的noexcept原因std::terminate.
有没有办法在编译时检测这些违规?在下面的示例中,问题很明显,但默认情况下没有编译器捕获它.我意识到在所有情况下都不可能,但肯定更简单的情况应该是可能的
#include <stdexcept>
void baz()
{
throw std::runtime_error("std::terminate awaits");
}
void bar()
{
baz();
}
void foo() noexcept
{
bar();
}
Run Code Online (Sandbox Code Playgroud)
链接到godbolt:https://godbolt.org/z/Ooet58
是否有我不知道的编译器标志?如何捕获这个静态分析工具呢?
C++ 中的 noexcept 如何改变程序集?我在 godbolt 中尝试了一些小功能,但程序集没有改变。
float pi()
//noexcept // no difference
{ return 3.14; }
int main(){
float b{0};
b = pi();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我正在寻找一个最小的工作示例,在其中我可以看到由于noexcept.
在优化代码的某些部分时,我决定检查是否可以将某些方法声明为noexcept,这归结为我对的数学函数的不完全了解<cmath>。
因此,我决定检查我使用的sin()和asin()(例如)是否为noexcept。
static_assert(noexcept(asin(1)));
static_assert(noexcept(sin(1)));
Run Code Online (Sandbox Code Playgroud)
它成功通过了,所以它们实际上是noexcept。我还查看了标准库实现中的相应定义:
template <class _A1>
inline _LIBCPP_INLINE_VISIBILITY
typename std::enable_if<std::is_integral<_A1>::value, double>::type
asin(_A1 __lcpp_x) _NOEXCEPT {return ::asin((double)__lcpp_x);}
Run Code Online (Sandbox Code Playgroud)
noexcept至少在我当前正在使用的实现中,这证实了它们的正确性。
但是,我无法确定这是否是标准要求的保证行为。因此,我想知道是否是必需的行为。如果不是这样,不要求他们成为的动机是noexcept什么?
我通常的参考书cppreference.com没有列出noexcept这些功能(请参见比较)。与C的兼容性可能会引起一些混淆;但是,我找不到令人信服的逻辑,因为<cmath>显然使用C ++标头,而不是C兼容标头。
复制时我有一个类型抛出:
struct A { A(const A&) { throw 1; } };
void doit(A)
{
}
int main()
{
A a;
doit(a);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
异常是在函数内部还是外部抛出?我可以将该函数声明为 noexcept 吗?
我想知道是否有一个技巧可以简化特征的编写以返回类型是否为noexcept 函数。目前我的实现如下,它只是一一列出所有可能性。可以使用标准以更简单的方式编写C++20吗?
// Default
template <class>
struct is_noexcept_function: std::false_type {};
// Variable template
template <class T>
inline constexpr bool is_noexcept_function_v
= is_noexcept_function<T>::value;
// Noexcept functions
template <class R, class... Args>
struct is_noexcept_function<R(Args...) noexcept>: std::true_type {};
template <class R, class... Args>
struct is_noexcept_function<R(Args...) const noexcept>: std::true_type {};
template <class R, class... Args>
struct is_noexcept_function<R(Args...) volatile noexcept>: std::true_type {};
template <class R, class... Args>
struct is_noexcept_function<R(Args...) const volatile noexcept>: std::true_type {};
// Noexcept lvalue-ref-qualified functions
template <class R, …Run Code Online (Sandbox Code Playgroud) 我正在尝试在不同的编译器上自己试验代码。我一直在尝试查找在某些函数上禁用异常的优势(通过二进制足迹)并将其与不禁用异常的函数进行比较,实际上我偶然发现了一个奇怪的情况,其中最好有异常比没有。
我一直在使用Matt Godbolt 的 Compiler Explorer进行这些检查,并且在 x86-64 clang 12.0.1 上进行了检查,没有任何标志(在 GCC 上这种奇怪的行为不存在)。
看看这个简单的代码:
auto* allocated_int()
{
return new int{};
}
int main()
{
delete allocated_int();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
非常简单,几乎删除了从函数返回的已分配指针allocated_int()。
正如预期的那样,二进制占用空间也很小:
allocated_int(): # @allocated_int()
push rbp
mov rbp, rsp
mov edi, 4
call operator new(unsigned long)
mov rcx, rax
mov rax, rcx
mov dword ptr [rcx], 0
pop rbp
ret
Run Code Online (Sandbox Code Playgroud)
此外,非常直接。但是当我将noexcept关键字应用于allocated_int()函数时,二进制膨胀。我将在此处应用生成的程序集:
allocated_int(): # @allocated_int()
push rbp
mov rbp, rsp
sub rsp, 16
mov …Run Code Online (Sandbox Code Playgroud)