如果我有一个示例函数,例如:
void func1(float a, float b, float c)
{
setA(a);
setB(b);
setC(c);
}
调用内联函数:
inline void setA(float a){ m_a = a; m_isValid = false; }
inline void setB(float b){ m_b = b; m_isValid = false; }
inline void setC(float c){ m_c = c; m_isValid = false; }
我应该关心“m_isValid = false”重复项还是编译器通过优化消除它们?
最佳答案
是的,这通常称为 Dead Store Elimination (用编译器的说法,读取 = 加载和写入 = 存储)。
一般来说,任何无用的操作都可以被编译器优化掉,前提是它可以证明你(用户)不会注意到它(在语言设置的范围内)。
特别是对于 Dead Store Elimination,它通常仅限于:
- 单个函数的主体(然而,内联在这里有帮助)
- 无需干预对不透明函数的调用
一些例子:
struct Foo { int a; int b; };
void opaque(Foo& x); // opaque, aka unknown definition
Foo foo() {
Foo x{1, 2};
x.a = 3;
return x; // provably returns {3, 2}
// thus equivalent to Foo foo() { return {3, 2}; }
}
Foo bar() {
Foo x{1, 2};
opaque(x); // may use x.a, so need to leave it at '1' for now
x.a = 3;
return x;
}
Foo baz() {
Foo x{1, 2};
opaque(x);
x.a = 1; // x.a may have been changed, cannot be optimized
return x;
}
请注意,是否连续存储相同的值并不重要,只要编译器能够证明在两次存储操作之间没有读取一个变量,它就可以安全地消除第一个。
特殊情况:根据 C++ 规范,加载/存储到 volatile
无法优化。这是因为 volatile
被指定为允许与硬件交互,因此编译器无法先验地知道硬件是否会在程序背后读取或写入变量。
另一种特殊情况:出于优化的目的,在多线程程序中使用的内存同步操作(fences、barrier 等)也可以阻止这种优化。这是因为,与 volatile
情况非常相似,同步意味着另一个执行线程可能已经修改了该线程背后的变量。
最后,像所有优化一样,它的有效性在很大程度上取决于对上下文的了解。如果证明 opaque
不读取或不写入 x.a
,则可以优化一些存储(如果编译器可以检查 的定义,则证明>不透明
),所以一般来说它真的依赖于内联和常量传播。
关于c++ - C++ 编译器会消除赋值重复吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18430671/