1

在 C++ 中,常量变量初始化中的数学声明是否需要一些额外的处理?或者现代编译器会在创建 .exe 文件时自动将数学计算的结果放入变量中?

所以例如:

MyClass::MyClass()
{
    const qint32 defaultX = 20;

    poButton1 = new PushButton(this);
    poButton1->move(defaultX,20);

    poButton1 = new PushButton(this);
    poButton1->move(defaultX,80);
    //...
}

是在方法使用(本例中为构造函数)中使用常量变量 (defaultX) 的代码示例。现在有时最好让开发人员说出价值的来源:

MyClass::MyClass()
{
    const qint32 defaultX = 800/2 - 244 + 12 + 32 - 180; //just an example!

    poButton1 = new PushButton(this);
    poButton1->move(defaultX,20);

    poButton1 = new PushButton(this);
    poButton1->move(defaultX,80);
    //...
}

当然他可以把它放在评论中,但让我们假设他想这样做(例如:他很愚蠢)。那么问题是:当初始化该类的对象时,是否计算了整个数学表达式(需要额外的处理),或者当现代编译器创建 .exe 时,它​​已经包含在第一个 MyClass 代码中看到的优化代码?

4

2 回答 2

3

不能保证,但大多数现代编译器确实会折叠常量表达式C++ 标准草案有一个说明,说常量表达式可以在翻译期间进行评估,来自5.19 常量表达式部分:

[注:常量表达式可以在翻译过程中求值。——尾注]

但我们可以使用以下代码在Godbolt上运行实验:

#include <iostream>
int func()
{
    const  int defaultX = 800/2 - 244 + 12 + 32 - 180; //just an example!

  return defaultX ;
}

int main()
{
  std::cout << func() ;
}

并看到它确实将其折叠为以下内容:

func():
  movl  $20, %eax   #,
  ret

在 C++11 中,您始终可以使用constexpr来确保在编译时对其进行评估:

constexpr  int defaultX = 800/2 - 244 + 12 + 32 - 180;

该标准确实对浮点常量表达式做了一个重要说明。由于缺乏对浮点运算准确性的规范,因此运行时和编译时的评估可能会产生不同的结果:

[ 注意:虽然在某些情况下必须在程序翻译期间计算常量表达式,但可以在程序执行期间计算其他表达式。由于本国际标准对浮点运算的准确性没有任何限制,因此未指定在翻译期间对浮点表达式的求值是否与对相同表达式的求值产生相同的结果(或对相同值的相同操作) ) 在程序执行期间。84 示例:

 bool f() {
  char array[1 + int(1 + 0.2 - 0.1 - 0.1)]; // Must be evaluated during translation
  int size = 1 + int(1 + 0.2 - 0.1 - 0.1); // May be evaluated at runtime
  return sizeof(array) == size;
 }

未指定 f() 的值是真还是假。—结束示例] —结束说明]

于 2014-08-07T18:02:35.980 回答
2

如果它可以折叠成单个值(在简单赋值的情况下必须如此),编译器应该注意将其压缩为单个值,尽管这可能取决于编译器的优化标志。您可能需要查看编译器发出的指令以确定。

更清楚地表达这一点的一种方法是在类本身之外声明常量,但对实现来说是本地的,并在类中使用它:

const qint32 myClassDefaultX = 800/2 - 244 + 12 + 32 - 180;

MyClass::MyClass() { ... }
于 2014-08-07T17:57:54.523 回答