Константы и оптимизация компилятора в С++

Я прочитал все советы по const-correctness в С++ и что это важно (частично), потому что это помогает компилятору оптимизировать ваш код. То, что я никогда не видел, является хорошим объяснением того, как компилятор использует эту информацию для оптимизации кода, даже хорошие книги не объясняют, что происходит за шторами.

Например, как компилятор оптимизирует метод, который объявляется const vs, который не является, а должен быть. Что происходит, когда вы вводите изменяемые переменные? Они влияют на эти оптимизации методов const?

Ответ 1

Пусть игнорируют методы и смотрят только на объекты const; у компилятора гораздо больше возможностей для оптимизации здесь. Если объект объявлен как const, то (ISO/IEC 14882: 2003 7.1.5.1 (4)):

За исключением того, что объявлен любой член класса изменяемый (7.1.1) может быть изменен, любой попытка изменить объект const в течение его жизни (3.8) приводит к undefined.

Позволяет игнорировать объекты, которые могут иметь изменяемые члены - компилятор может предположить, что объект не будет изменен, поэтому он может произвести значительную оптимизацию. Эти оптимизации могут включать такие вещи, как:

  • включение значения объекта непосредственно в коды операций с машинами
  • полное устранение кода, который никогда не может быть достигнут, поскольку объект const используется в условном выражении, которое известно во время компиляции.
  • разворачивание цикла, если объект const контролирует количество итераций цикла

Обратите внимание, что этот материал применяется только в том случае, если фактический объект является const - он не применяется к объектам, к которым обращаются через указатели или ссылки на константы, поскольку эти пути доступа могут приводить к объектам, которые не являются константами (они даже четко определены для изменения объекты, хотя const указатели/ссылки, пока фактический объект не является константой, и вы отбрасываете константу пути доступа к объекту).

На практике я не думаю, что есть компиляторы, которые выполняют любую значительную оптимизацию для всех типов объектов const. но для объектов, которые являются примитивными типами (ints, chars и т.д.), я думаю, что компиляторы могут быть довольно агрессивными в оптимизации использование этих элементов.

Ответ 2

Я думаю, что ключевое слово const было в основном введено для проверки компиляции семантики программы, а не для оптимизации.

Herb Sutter, в статье GotW # 81, очень хорошо объясняет, почему компилятор не может ничего оптимизировать при передаче параметров по ссылке const, или при объявлении значения const. Причина в том, что компилятор не имеет никакого способа убедиться, что ссылка на объект не будет изменена, даже если объявлена ​​const: можно использовать const_cast, или какой-либо другой код может иметь неконстантную ссылку на один и тот же объект.

Однако, цитируя статью Херба Саттера:

Существует [только] один случай, когда говорится "const" действительно может что-то означать, и то есть когда объекты создаются const на точка, в которой они определены. В этом случае, компилятор может часто успешно поставил такой "действительно сост", объектов в постоянное запоминающее устройство [...].

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

Ответ 3

начинается ручная работа

По сути, чем раньше данные фиксированы, тем больше компилятор может перемещаться по фактическому назначению данных, гарантируя, что конвейер не остановится

конец записи

Ответ 4

Мех. Const-correctness - это скорее проверка стиля/ошибки, чем оптимизация. Полноценный оптимизирующий компилятор будет следовать за использованием переменных и может определять, когда переменная эффективно const или нет.

Добавленный к этому, компилятор не может полагаться на то, что вы говорите правду - вы можете отбросить const внутри библиотечной функции, о которой она не знает.

Так что да, const-correctness - это достойная цель, но он не говорит компилятору ничего, что он не сможет понять сам, предполагая хороший оптимизирующий компилятор.

Ответ 5

Он не оптимизирует функцию, объявленную как const.

Он может оптимизировать функции, которые вызывают функцию, объявленную как const.

void someType::somefunc();

void MyFunc()
{
    someType A(4);   // 
    Fling(A.m_val);
    A.someFunc();
    Flong(A.m_val);
}

Здесь для вызова Fling valud A.m_val необходимо загрузить в регистр CPU. Если someFunc() не const, значение нужно перезагрузить перед вызовом Flong(). Если someFunc является const, тогда мы можем вызвать Flong со значением, которое все еще находится в регистре.

Ответ 6

Основная причина наличия методов как const для константной корректности, а не для возможной оптимизации компиляции самого метода.

Если переменные являются константами, они могут (теоретически) быть оптимизированы. Но только компилятор видит область видимости. После того, как компилятор должен разрешить их изменять с помощью const_cast в другом месте.

Ответ 7

Все это верные ответы, но ответы и вопрос, похоже, предполагают одно: оптимизация компилятора действительно имеет значение.

Существует только один тип кода, в котором важна оптимизация компилятора, то есть в коде

  • плотная внутренняя петля,
  • в коде, который вы компилируете, в отличие от сторонней библиотеки,
  • не содержит вызовов функций или методов (даже скрытых),
  • где счетчик программ тратит заметную часть своего времени

Если остальные 99% кода оптимизированы до N-й степени, это не будет иметь разницы в разнице, потому что это имеет значение только в коде, где счетчик программ фактически проводит время (которое вы можете найти по выборке).

Ответ 8

Я был бы удивлен, если бы оптимизатор фактически помещал много акций в объявление const. Существует много кода, который в конечном итоге лишит const-ness, это был бы очень безрассудный оптимизатор, который полагался бы на выражение программиста, чтобы предположить, когда состояние может измениться.

Ответ 9

const-correctness также полезна в документации. Если функция или параметр указана как const, мне не нужно беспокоиться о том, что значение менялось из-под моего кода (если кто-то еще в команде не очень озорной). Я не уверен, что это было бы действительно стоит, если бы оно не было встроено в библиотеку.

Ответ 10

Наиболее очевидной точкой, где const является прямая оптимизация, является передача аргументов функции. Часто важно обеспечить, чтобы функция не изменяла данные, поэтому единственными реальными выборами для сигнатуры функции являются следующие:

void f(Type dont_modify); // or
void f(Type const& dont_modify);

Конечно, настоящая магия здесь передаёт ссылку, а не создает (дорогую) копию объекта. Но если ссылка не была отмечена как const, это ослабит семантику этой функции и будет иметь отрицательные эффекты (например, более сложное отслеживание ошибок). Поэтому const позволяет оптимизировать здесь.

/EDIT: на самом деле хороший компилятор может анализировать поток управления функцией, определять, что он не изменяет аргумент и не делает оптимизацию (передавая ссылку, а не копию). const здесь просто помощь для компилятора. Однако, поскольку С++ имеет довольно сложную семантику, и такой анализ потока управления может быть очень дорогостоящим для больших функций, мы, вероятно, не должны полагаться на компиляторы для этого. У кого-нибудь есть данные, чтобы поддержать меня/доказать, что я неправ?

/EDIT2: и да, как только пользовательские конструкторы копирования вступят в игру, это становится еще более сложным, потому что компиляторам, к сожалению, не разрешается пропустить их в этой ситуации.

Ответ 11

Этот код,

class Test
{
public:
  Test (int value) : m_value (value)
  {
  }

  void SetValue (int value) const
  {
    const_cast <Test&>(*this).MySetValue (value);
  }

  int Value () const
  {
    return m_value;
  }

private:
  void MySetValue (int value)
  {
    m_value = value;
  }

  int
    m_value;
};

void modify (const Test &test, int value) 
{
  test.SetValue (value);
}

void main ()
{
  const Test
    test (100);

  cout << test.Value () << endl;
  modify (test, 50);
  cout << test.Value () << endl;
}

выходы:

100
50

что означает, что объявленный объект const был изменен в функции-член const. Наличие const_cast (и ключевое слово mutable) на языке С++ означает, что ключевое слово const не может помочь компилятору в создании оптимизированного кода. И, как я указывал в своих предыдущих сообщениях, это может даже привести к неожиданным результатам.

Как правило:

const!= optimization

Фактически, это законный модификатор С++:

volatile const

Ответ 12

const помогает компиляторам оптимизировать главным образом потому, что он позволяет вам писать оптимизируемый код. Если вы не введете const_cast.