关于c++优化的问题

Question about optimization in C++

本文关键字:问题 优化 c++ 关于      更新时间:2023-10-16

我读到过c++标准允许优化到一定程度,这实际上会阻碍预期的功能。当我这么说的时候,我说的是返回值优化,你可能在复制构造函数中有一些逻辑,但是编译器优化了调用。

我觉得这有点不好,因为不知道这一点的人可能会花费相当长的时间来修复由此导致的错误。

我想知道的是是否有任何其他情况下编译器的过度优化可以改变功能。

例如:

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

可以优化为单个x=1;

假设我有:

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

这个也可以优化吗?可能不是最好的例子,但我希望你明白我的意思…

省略复制操作 是唯一允许编译器优化到副作用明显改变的情况。不要依赖被调用的复制构造函数,编译器可能会优化掉这些调用。

对于其他一切,"as-if"规则适用:编译器可以按照自己的喜好进行优化,只要可见的副作用与编译器根本没有优化的效果相同。

("可见的副作用"包括,例如,写入控制台或文件系统的东西,但不包括运行时和CPU风扇速度。)

它可能是优化的,是的。但是您仍然可以对过程进行一些控制,例如,假设代码为:

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 = 1;[010B1004]好的,好的[010B1006 .[010B1007]; [y]Y = 1;[010B100A] [y]Y = 1;[010B100D] [y]Y = 1;010B1010 mov双字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什么都不做,并立即返回零。

这将取决于class A是如何实现的,编译器是否可以看到实现以及它是否足够聪明。例如,如果class A中的operator=()有一些副作用,那么这种优化将改变程序的行为,并且是不可能的。

优化不(适当地说)"删除复制或赋值的调用"。它将一个有限状态机转换为另一个具有相同外部行为的有限状态机。

现在,如果你反复调用

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

编译器做什么取决于operator=实际是什么。如果编译器发现调用没有机会改变程序的状态("程序的状态"是"比作用域可以访问的作用域更长"),它将剥离它。如果这不能被"证明",调用将留在原地。

无论编译器会做什么,不要太担心:编译器不能(根据约定)改变程序的外部逻辑或程序的一部分。

我不太了解c++,但我目前正在阅读编译器-原理,技术和工具

下面是他们关于代码优化部分的一个片段:

与机器无关的代码优化阶段试图改进中间代码,以便产生更好的目标代码。通常更好意味着更快,但可能需要其他目标,例如更短的代码,或消耗更少功率的目标代码。例如a直接算法生成中间代码(1.3)使用树表示中每个操作符的指令来自语义分析器。一个简单的中间代码生成算法后再进行代码优化是一种合理的方法生成好的目标代码。优化器可以推导出将60从整数到浮点数的转换可以完成一次和对于所有在编译时,所以inttofloat操作可以消除通过将整数6-替换为浮点数60.0。而且t3只被使用一次,将它的值传递给id1Optimizer可以将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
我想说的是,代码优化应该在更深的层次上进行,因为代码处于如此简单的状态,这并不影响你的代码做什么

我在使用const变量和const_cast时遇到了一些麻烦。当编译器用于计算其他东西时,它会产生不正确的结果。const变量被优化掉了,它的旧值变成了一个编译时常量。真正的"意外行为"。好吧,也许不是;)

的例子:

const int x = 2;
const_cast<int&>(x) = 3;
int y = x * 2;
cout << y << endl;