我已经读过C ++标准允许优化到可以实际阻碍预期功能的程度。当我这样说时,我说的是返回值优化,你可能在拷贝构造函数中实际上有一些逻辑,但编译器优化了调用。
我发现这有些不好,因为有些人不知道这可能会花费相当多的时间修复由此造成的错误。
我想知道的是,是否存在编译器过度优化可能会改变功能的任何其他情况。
例如:
int x = 1;
x = 1;
x = 1;
x = 1;
可能会优化为单个x = 1;
假设我有:
class A;
A a = b;
a = b;
a = b;
这可能也可以优化吗?可能不是最好的例子,但我希望你知道我的意思......
答案 0 :(得分:12)
完成复制操作 是允许编译器优化到 副作用明显改变 <的唯一情况/ strong>即可。不要依赖于被调用的复制构造函数,编译器可能会优化这些调用。
对于其他所有内容,“as-if”规则适用:编译器可以根据需要进行优化,只要可见的副作用与编译器根本没有优化的相同。
(“可见副作用”包括,例如,写入控制台或文件系统的内容,但不包括运行时和CPU风扇速度。)
答案 1 :(得分:3)
可能会进行优化,是的。但您仍然可以控制该过程,例如,假设代码:
int x = 1;
x = 1;
x = 1;
x = 1;
volatile int y = 1;
y = 1;
y = 1;
y = 1;
如果在此片段下方既不使用x也不使用y,则VS 2010会生成代码:
int x = 1; x = 1; x = 1; x = 1; volatile int y = 1; 010B1004 xor eax,eax 010B1006 inc eax 010B1007 mov dword ptr [y],eax y = 1; 010B100A mov dword ptr [y],eax y = 1; 010B100D mov dword ptr [y],eax y = 1; 010B1010 mov dword ptr [y],eax
即,优化使用“x”去除所有行,并将所有四行留下“y”。这就是 volatile 的工作原理,但重点是你仍然可以控制编译器为你做什么。
无论是类还是原始类型 - 都取决于编译器,它的优化上限有多复杂。
另一个用于研究的代码片段:
class A
{
private:
int c;
public:
A(int b)
{
*this = b;
}
A& operator = (int b)
{
c = b;
return *this;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
int b = 0;
A a = b;
a = b;
a = b;
return 0;
}
Visual Studio 2010优化将所有代码都删除为空,在发布版本中使用“完全优化”_tmain什么都不做,并立即返回零。
答案 2 :(得分:1)
这取决于class A
的实现方式,编译器是否可以看到实现以及它是否足够智能。例如,如果operator=()
中的class A
有一些副作用,那么优化会改变程序行为并且是不可能的。
答案 3 :(得分:0)
优化不会(在适当的时候)“删除对复制或分配的调用”。 它将有限状态机转换为另一个有限状态,机器具有相同的外部行为。
现在,如果你重复打电话
a=b; a=b; a=b;
编译器的作用取决于operator=
实际上是什么。
如果编译器发现调用没有机会改变程序的状态(并且“程序的状态”是“所有东西都长于范围可以访问的范围”),它将剥离它。
如果无法“证明”,则呼叫将保持不变。
无论编译器做什么,都不要过于担心:编译器不能(通过契约)更改程序或部分程序的外部逻辑。
答案 4 :(得分:-1)
我不太了解c ++,但目前正在阅读编译器 - 原理,技术和工具
这是他们关于代码优化的部分的片段:
与机器无关的代码优化阶段试图改进 中间代码,以便产生更好的目标代码。平时 更好意味着更快,但可能需要其他目标,例如 更短的代码或消耗更少功率的目标代码。例如a 直接算法使用生成中间代码(1.3) 来自树表示中的每个运算符的指令 来自语义分析器。一个简单的中间代码生成 算法遵循代码优化是一种合理的方法 生成良好的目标代码。优化者可以推测出这一点 将60从整数转换为浮点可以进行一次和 对于所有在编译时,所以可以消除inttofloat操作 通过用浮点数60.0替换整数6-。 此外,t3仅使用一次将其值传递给id1,所以 优化器可以将1.3转换为较短的序列(1.4)
1.3
t1 - intoffloat(60
t2 -- id3 * id1
ts -- id2 + t2
id1 t3
1.4
t1=id3 * 60.0
id1 = id2 + t1
所有这一切我的意思是说代码优化应该处于更深层次,并且因为代码处于这样一个简单的状态并不会影响代码的作用
答案 5 :(得分:-1)
我对const变量和const_cast
有些麻烦。当用于计算其他内容时,编译器产生了错误的结果。 const变量被优化掉了,它的旧值被制作成编译时常量。真正的“意外行为”。好吧,也许不是;)
示例:
const int x = 2;
const_cast<int&>(x) = 3;
int y = x * 2;
cout << y << endl;