Я работаю над презентацией, которая демонстрирует различные оптимизации на C++ и зацикливается на примере, где const
позволяет им.G ++: Перемещение на другую единицу перевода прерывает «оптимизацию const»?
Рассмотрим следующий код:
object.h
class Object {
int i1;
int i2;
public:
Object(int i1_, int i2_) : i1(i1_), i2(i2_) {}
int getI1() const { return i1; }
int getI2() const { return i2; }
std::pair<int, int> calculate() const {
return std::pair<int, int>(i1 + i2, i1 * i2);
}
};
constopt.cpp
#include <iostream>
#include "object.h"
int main() {
Object o(10, 20);
std::cout << o.getI1() << " + " << o.getI2() << " = "
<< o.calculate().first << std::endl
<< o.getI1() << " * " << o.getI2() << " = "
<< o.calculate().second << std::endl;
return 0;
}
Когда calculate()
является встраиваемой, все отлично, G ++ непосредственно передает константы (10 и 20) до operator <<
кеширование getI1()
и getI2()
вызовов:
mov $0xa,%esi
mov $0x601080,%edi
callq 0x400740 <[email protected]>
Но когда я перехожу calculate()
в отдельный блок перевода, он вынуждает i1
и i2
, чтобы быть извлечены дважды (до и после o.calculate().first
):
mov (%rsp),%esi
mov 0x4(%rsp),%r14d
mov $0x601080,%edi
callq 0x400740 <[email protected]>
Я не вижу никакой разницы , потому что getI1()
не полагается на какие-либо побочные эффекты, которые могут быть созданы calculate()
и Object
, должен быть const, даже если calculate()
находится в отдельной единицы перевода.
Разве что G ++ недостаточно умен или он не может выполнять оптимизацию в таких случаях? Мое предположение состоит в том, что он может кэшировать getI1()
и getI2()
звонки пришли из этого ответа: How does const after a function optimize the program?
Я использую gcc версию 4.8.1. Я пробовал оба -O и -O2.
Кажется, что const
не используется в GCC оптимизатора в этом случае. Вместо этого он выполняет собственное копание (которое не может выполняться в разных единицах перевода) и ищет pure and const functions. Функции могут быть отмечены вручную с помощью __attribute__((const))
. Фаза, которая устраняет дополнительные вызовы getI*()
, называется FRE (Полное устранение избыточности).
Возможный дубликат http://stackoverflow.com/questions/9767395 –
Составители не оптимизируются на основе константы. Константа только там, чтобы помочь разработчикам. 'const_cast' всегда присутствует, и компилятор не имеет возможности узнать об этом. – sbabbi
@sbabbi Можете ли вы найти ссылку для этого? Я был бы очень удивлен, если это так. – Shade