Распределение памяти для константных переменных - PullRequest
6 голосов
/ 14 января 2012

Я читаю книгу, в которой упоминается это

Если компилятору известно каждое использование const, ему не нужно выделять место для его хранения.Например:

  1. const int c1=1;
  2. const int c3=my_f(3);
  3. extern const int c4;

Учитывая, что значения c3 и c4не известное как время компиляции, для c3 и c4 должно быть выделено хранилище.

Я ничего не понял.Мои сомнения:

Что значит держать здесь?Разве не нужно все хранить в памяти?Для c1, у нас есть какое-либо распределение памяти?

Пожалуйста, проясните мои сомнения.

Спасибо.

Ответы [ 3 ]

4 голосов
/ 14 января 2012

c1 отличается от двух других констант тем, что инициализируется литеральным значением .Это позволяет компилятору размещать это значение везде, где используется константа, например:

int x = z + c1;

может быть заменено на

int x = z + 1;

Это означает, что компилятору не нужно выделять пространство и хранить1 в нем.

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

int x = z + c4;

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

2 голосов
/ 14 января 2012

Const имеет 2 варианта использования - замена макросов (константных выражений), а также неизменяемых данных.

Это утверждение:

const int c1=1;

По существу, это типобезопасная версия:

#define c1 1

такой, что этот код:

int foo = c1;

Может быть просто скомпилирован как:

int foo = 1;

Что эффективнее.

С другой стороны, это:

const int c3=my_f(3);

Используется как неизменный c3. Вероятно, он существует в памяти, но вы не можете его изменить. По сути это более безопасная версия int c3=my_f(3);.

Чтобы проиллюстрировать это:

int a1[c1];
int a2[c3];

a1 допустим, так как компилятор может вывести a1 как константное выражение. a2 нет, так как в то время как c3 является const, он может быть неизвестен во время компиляции.

C ++ 11 добавляет ключевое слово constexpr, которое похоже на const, но более строгое, чем const. Только c1 и c2 могут быть constexpr. c3 также может быть, хотя для этого потребуется my_f тоже.

1 голос
/ 14 января 2012

Как интегральное выражение константы, компилятор имеет полное право использовать постоянное свертывание, чтобы удалить его из программы. Это только неправда, если вы берете его адрес. Кроме того, современный оптимизирующий компилятор может использовать LTO, встраивание и постоянное свертывание, чтобы сделать то же самое с c3 и c4, если это возможно.

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

Редактировать: сворачивание констант - это то, где компилятор вычисляет выражения во время компиляции, а не во время выполнения. Например, вы можете по закону сделать int x[3 + 4];, где 3 + 4 вычисляется во время компиляции. Некоторые примеры, в частности те, которые связаны с ICE, соответствуют стандарту, но реализация может выполнить больше, если это возможно. LTO - это оптимизация времени соединения, в которой компилятор выполняет оптимизацию для единиц перевода, когда они связаны друг с другом.

Это означает, что компилятор может встроить тело my_f, а затем (в зависимости от тела) свернуть его, чтобы сделать c3 константным выражением, а затем константно сложить его в том месте, где он используется, и не выделять Это. Для c4 LTO может привести к значению c4 в качестве константного выражения, в этом случае оно также может быть свернуто и удалено.

В C ++ 11 есть constexpr функции, которые позволяют сделать гораздо больше в этом регионе.

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