C++中的noexcept如何改变汇编代码?

5
C++中的noexcept如何改变汇编代码?我在godbolt上尝试了一些小函数,但是发现汇编代码没有改变
float pi() 
//noexcept // no difference
{ return 3.14; }

int main(){
    float b{0};
    b = pi();
    return 0;
}

我正在寻找一个最小的工作示例,以便我可以看到由于noexcept而导致汇编中的变化。


4
在某些情况下,这可能是一个巨大的变化,比如在 std::vector<MyType> 中,如果 MyType 的移动构造函数不是 noexceptstd::vector 在重新调整大小时必须复制元素,而不是仅仅移动它们。在其他情况下,就像你所看到的那样,这可能没有任何区别。简而言之,noexcept 不会“改变程序集”,但它提供了库代码可以依赖的语义含义,这最终可能导致程序集中的重大变化,或者根本不会有程序集的变化。 - Justin
5
一个带有 noexcept 声明的函数体还可以以更高效的方式编译,因为在异常发生时不需要正确地销毁局部变量。请参见此处:https://dev59.com/PV8e5IYBdhLWcg3wHXaJ - alter_igel
你的例子太简单了,编译器已经知道它是noexcept的,不需要你告诉它。使用一个更复杂的例子,比如调用另一个代码文件中的进一步函数,这样编译器就无法确定它是否是noexcept的。 - Aganju
1
当然,noexcept语句也可能会导致调用函数的不同汇编代码(特别是如果该函数包含try-catch语句)。 - Martin Rosenau
1
noexcept 只有在以下情况下才会产生影响:A)存在需要析构的非平凡项,B)可能抛出异常,因此编译器必须处理这些情况。 - Mgetz
1个回答

3

可以直接使用析构函数而不是检查 noexcept 状态的反射来构建非常简单的示例

void a(int);
void b() noexcept;
void c(int i) {
  struct A {
    int i;
    ~A() {a(i);}
  } a={i};
  b();
  a.i=1;
}

在这里,noexcept 允许忽略调用者中 a 的初始化,因为析构函数无法观察到它。
struct B {~B();};
void f();
void g() noexcept {
  B b1;
  f();
  B b2;
}

在这里,noexcept允许省略在被调用者抛出异常时需要的帧信息。这取决于(非常普遍的)决定,在调用std::terminate时不展开堆栈。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接