将一个数学计算写成一个变量中常量表达式的值,这会增加计算工作量吗? 在C++中,常数变量初始化中的数学声明是否需要额外的处理?或者现代编译器在创建.exe文件时会自动将数学计算结果放入变量中

将一个数学计算写成一个变量中常量表达式的值,这会增加计算工作量吗? 在C++中,常数变量初始化中的数学声明是否需要额外的处理?或者现代编译器在创建.exe文件时会自动将数学计算结果放入变量中,c++,compiler-optimization,constant-expression,C++,Compiler Optimization,Constant Expression,例如: MyClass::MyClass() { const qint32 defaultX = 20; poButton1 = new PushButton(this); poButton1->move(defaultX,20); poButton1 = new PushButton(this); poButton1->move(defaultX,80); //... } 是在方法用法(本例中为构造函数)中使用常量变量(defa

例如:

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代码中看到的优化代码?

如果可以将其压缩为单个值,在简单赋值的情况下,编译器应该注意将其压缩为一个奇异值,尽管这可能取决于编译器的优化标志。您可能希望查看编译器发出的指令,以确定是否正确

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

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

MyClass::MyClass() { ... }

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

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

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

MyClass::MyClass() { ... }

这是不能保证的,但大多数现代编译器确实会折叠,其中有一条注释说,常量表达式可以在翻译过程中进行计算,参见第
5.19节
constant expressions:

[注:在翻译过程中可以计算常量表达式。-结束注]

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

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

  return defaultX ;
}

int main()
{
  std::cout << func() ;
}
在C++11中,您始终可以使用以确保在编译时对其进行计算:

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()的值是真是假。-结束示例]-结束注释]


这是不能保证的,但大多数现代编译器确实会折叠,其中有一条注释说,常量表达式可以在翻译过程中进行计算,参见第
5.19节
constant expressions:

[注:在翻译过程中可以计算常量表达式。-结束注]

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

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

  return defaultX ;
}

int main()
{
  std::cout << func() ;
}
在C++11中,您始终可以使用以确保在编译时对其进行计算:

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()的值是真是假。-结束示例]-结束注释]


只要表达式是常量,一个好的编译器就会对它进行优化,并用表达式的结果替换defaultX。在C++11中,您可能希望使用
constexpr
,理论上,这两个方向都没有保证。事实上,你能找到的每一个半途而废的编译器都会在编译时进行编译。为什么你认为这样做很愚蠢?可能有理由澄清如何构造值,或者希望在公式中使用其他常量表达式。不,这不会损害运行时性能,编译器将在编译时正确计算所有内容,就像启动袖珍计算器一样。@πάνταῥεῖ 我提出了一个“愚蠢”的解释,因为一旦有可能在注释中编写公式,而只将结果放入代码中,同时有可能“损害”运行时性能,就没有合理的理由这样做:)只要表达式是常量,一个好的编译器将对其进行优化,并用表达式的结果替换defaultX。在C++11中,您可能希望使用
constexpr
,理论上,这两个方向都没有保证。事实上,你能找到的每一个半途而废的编译器都会在编译时完成它。为什么你认为它对d来说是愚蠢的呢