提问人:Luchian Grigore 提问时间:9/22/2011 更新时间:9/24/2011 访问量:335
关于 C++ 优化的问题
Question about optimization in C++
问:
我读到C++标准允许优化到实际上会阻碍预期功能的程度。当我这么说时,我说的是返回值优化,其中复制构造函数中实际上可能有一些逻辑,但编译器会优化调用。
我发现这有点糟糕,因为不知道这一点的人可能会花相当多的时间来修复由此导致的错误。
我想知道的是,是否有任何其他情况,编译器的过度优化会改变功能。
例如,类似以下内容:
int x = 1;
x = 1;
x = 1;
x = 1;
可以优化为单个 x=1;
假设我有:
class A;
A a = b;
a = b;
a = b;
这是否也可以优化?可能不是最好的例子,但我希望你明白我的意思......
答:
省略复制操作是允许编译器优化到副作用明显变化的唯一情况。不要依赖被调用的复制构造函数,编译器可能会优化这些调用。
对于其他所有内容,“假设”规则都适用:编译器可以随心所欲地优化,只要可见的副作用与编译器根本没有优化相同。
(例如,“可见的副作用”包括写入控制台或文件系统的内容,但不包括运行时和 CPU 风扇速度。
评论
这将取决于如何实现,编译器是否能看到实现以及它是否足够智能。例如,如果 in 有一些副作用,例如优化 out 会改变程序行为,这是不可能的。class A
operator=()
class A
它可能是优化的,是的。但是你仍然对这个过程有一定的控制权,例如,假设代码:
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不执行任何操作并立即返回零。
我对 c++ 了解不多,但目前正在阅读编译器原理、技术和工具
以下是他们关于代码优化的部分的片段:
独立于机器的代码优化阶段尝试改进 中间代码,以便生成更好的目标代码。通常 更好意味着更快,但可能需要其他目标,例如 较短的代码,或消耗较少功率的目标代码。例如 简单的算法使用 树表示中每个运算符的指令 来自语义分析器。简单的中间代码生成 算法后跟代码优化是一种合理的方法 生成良好的目标代码。Optimizar 可以推断 可以将 60 从整数转换为浮点数一次,并且 在编译时,可以消除 inttofloat 操作 通过将整数 6- 替换为浮点数 60.0。 此外,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
总而言之,我的意思是说代码优化应该在更深层次上进行,因为代码处于如此简单的状态,所以不会影响代码的功能
优化不会(用正确的术语)“删除对复制或分配的调用”。 它将有限状态机转换为另一个有限状态,即具有相同外部行为的机器。
现在,如果你废除调用
a=b; a=b; a=b;
编译器执行的操作取决于实际执行的操作。
如果编译器发现调用没有机会更改程序的状态(并且“程序状态”是“所有内容都比作用域可以访问的作用域长”),它将将其剥离。
如果无法“证明”这一点,则调用将保持不变。operator=
无论编译器会做什么,都不要太担心:编译器不能(通过合同)改变程序或程序的一部分的外部逻辑。
我在 const 变量和 .编译器在用于计算其他内容时会产生不正确的结果。const 变量被优化掉了,它的旧值被做成一个编译时常量。真正的“意外行为”。好吧,也许不是;)const_cast
例:
const int x = 2;
const_cast<int&>(x) = 3;
int y = x * 2;
cout << y << endl;
评论
const_cast
const
const
operator
const
const
评论