Написание математического вычисления как значения постоянного выражения в переменной инициализации увеличивает вычислительную работу?

В 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 ?

1

Решение

Это не гарантируется, но большинство современных компиляторов действительно свернут постоянное выражение, проект стандарта 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 () истинным или ложным. — конец примера] — конец заметки]

3

Другие решения

Если его можно свернуть в одно значение, которое должно быть в случае простого присваивания, компилятор должен позаботиться о его сжатии до единственного значения, хотя это может зависеть от флагов оптимизации вашего компилятора. Возможно, вы захотите взглянуть на инструкции, выпущенные вашим компилятором, чтобы быть уверенным.

Один из способов выразить это более четко — объявить константу вне самого класса, но локально для реализации и использовать ее внутри класса:

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

MyClass::MyClass() { ... }
2