关于C ++优化的问题

时间:2011-09-22 15:21:47

标签: c++ optimization

我已经读过C ++标准允许优化到可以实际阻碍预期功能的程度。当我这样说时,我说的是返回值优化,你可能在拷贝构造函数中实际上有一些逻辑,但编译器优化了调用。

我发现这有些不好,因为有些人不知道这可能会花费相当多的时间修复由此造成的错误。

我想知道的是,是否存在编译器过度优化可能会改变功能的任何其他情况。

例如:

int x = 1;
x = 1;
x = 1;
x = 1;

可能会优化为单个x = 1;

假设我有:

class A;

A a = b;
a = b;
a = b;

这可能也可以优化吗?可能不是最好的例子,但我希望你知道我的意思......

6 个答案:

答案 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;