Константы и оптимизация компилятора в C ++ - PullRequest
49 голосов
/ 17 октября 2008

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

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

Ответы [ 12 ]

54 голосов
/ 17 октября 2008

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

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

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

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

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

35 голосов
/ 17 октября 2008

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

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

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

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

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

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

6 голосов
/ 17 октября 2008

начинается махание рукой

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

конец ручного махания

5 голосов
/ 17 октября 2008

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

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

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

3 голосов
/ 17 октября 2008

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

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

3 голосов
/ 17 октября 2008

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

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

void someType::somefunc();

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

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

2 голосов
/ 23 декабря 2008

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

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

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

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

1 голос
/ 24 декабря 2008

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

1 голос
/ 17 октября 2008

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

0 голосов
/ 17 октября 2008

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...