c++ - 我可以告诉我的编译器忽略语句或函数的副作用吗?

标签 c++ compiler-optimization side-effects compiler-options elision

假设我的代码具有以下功能:

inline int foo() {
    bar();
    int y = baz();
    return y;
}
并假设 bar()baz()有副作用。
如果我写:
int z = foo();
printf("z is %d\n", z);
那么显然两者都是bar()baz()必须被执行。但如果我写:
foo();
并且不使用返回值,这是调用 baz() 的唯一原因是因为它的副作用。
有没有一种方法可以告诉我的编译器(对于 GCC、clang、MSVC、Intel 中的任何一个),例如“您可以忽略 baz() 的副作用,以便决定是否对其进行优化”?或者“为了决定是否优化它,您可能会忽略此指令的副作用”?
这个问题是针对 C 和 C++ 提出的,但可能与各种过程语言相关。让我们使用 C++,因为这是我现在最常用的。
笔记:
  • bar() , baz()不在我的控制之下。
  • 签名foo()不得更改。当然我可以使用一些代理并申请 baz()懒洋洋地,如果我愿意的话;或者只是为不使用 y 的情况写一个不同的函数.这不是我要问的。
  • 最佳答案

    作为标准 C 和 C++ 的扩展,gcc 和 clang 支持 pure function attribute它通知编译器该函数没有副作用并且可以删除不需要的调用。如果你用这个属性声明一个函数,编译器会相信你,即使你在撒谎。

    #include <iostream>
    
    static int foo() __attribute__((pure));
    
    static int foo() {
      std::cout << "I am a side effect!" << std::endl;
      return 17;
    }
    
    int main() {
      foo();
      return 0;
    }
    
    This prints no output.请注意 clang将警告您忽略 pure 的返回值功能。
    (特别是,当你在 C 中做类似的事情时, gcc optimizes out the call with -O0 ,但是 leaves it in with -O2 !)
    函数的定义不需要在范围内才能工作,即使先前的声明已经在范围内,您也可以重新声明具有此属性的函数。所以它也可以用于库函数。 Example.
    当然,对编译器撒谎总是由您自己承担风险,并且可以想象这可能会产生我没有想到的潜在不良影响。如果您愿意仔细检查生成的代码以确保它真的按照您的意愿行事,这可能是一个有用的技巧,但我不会太相信它。

    关于c++ - 我可以告诉我的编译器忽略语句或函数的副作用吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64177972/

    相关文章:

    python - Pytest:模拟具有不同 side_effect 的相同方法的多次调用

    C++如何将内存中的文件流保存到另一个位置

    c++ - 替代函数包装器

    c - 有没有办法绕过 C 中的编译器优化?

    haskell - 函数式编程: Where does the side effect actually happen?

    haskell - 我将如何想象 Haskell 中基于像素的渲染?

    c++ - 如何使 if else 语句与 cin 语句一起使用?

    c++ - "inline"函数定义的目的是什么?

    C++常量折叠素数循环

    javascript - 在已编译的 GWT 代码中实例化对象