const против enum в D

Посмотрите эту цитату с здесь внизу страницы. . (Я считаю, что цитируемый комментарий о consts относится и к invariants)

Перечисления отличаются от констант тем, что они не занимают места в конечном выводимом объекте/библиотеке/исполняемом файле, тогда как константы это делают.

Таким образом, очевидно, что value1 будет раздувать исполняемый файл, а value2 рассматривается как литерал и не отображается в объектном файле.

const int value1 = 0xBAD;
enum int value2 = 42;

Вернувшись в C++, я всегда предполагал, что это было связано с устаревшими причинами и старыми компиляторами, которые не могли оптимизировать константы. Но если это все еще верно в D, за этим должна быть более глубокая причина. Кто-нибудь знает, почему?


person zildjohn01    schedule 04.03.2009    source источник


Ответы (5)


Как и в C++, перечисление в D выглядит как "консервированный целочисленный литерал" (редактировать: удивительно, D2 даже поддерживает поплавки и строки). Его счетчики не имеют местоположения. Они просто нематериальны как ценности без идентичности.

Размещение enum является новым в D2. Сначала он определяет новую переменную. Это не lvalue (поэтому вы также не можете взять его адрес). Ан

enum int a = 10; // new in D2

Как

enum : int { a = 10 }

Если я могу доверять своим плохим знаниям D. Итак, a здесь не является lvalue (нет местоположения, и вы не можете взять его адрес). Константа, однако, имеет адрес. Если у вас есть глобальная (не уверен, что это правильная терминология D) константная переменная, компилятор обычно не может оптимизировать ее, потому что он не знает, какие модули могут получить доступ к этой переменной или могут получить ее адрес. Поэтому ему нужно выделить место для хранения.

Я думаю, что если у вас есть локальная константа, компилятор все равно может оптимизировать ее, как и в C++, потому что компилятор знает, глядя на ее область видимости, заинтересован ли кто-нибудь в ее адресе или все просто принимают ее значение.

person Johannes Schaub - litb    schedule 04.03.2009

Ваш фактический вопрос; почему enum/const в D такие же, как и в C++; кажется без ответа. К сожалению, для такого выбора нет веских причин. Я считаю, что это был просто непреднамеренный побочный эффект в C++, который де-факто стал шаблоном. В D нужен был такой же паттерн, и Уолтер Брайт решил, что надо сделать как в C++, чтобы те, кто придет оттуда, поняли, что делать... На самом деле перед этим довольно глупым ИМХО решением использовалось ключевое слово manifest вместо enum для этого варианта использования.

person larsivi    schedule 04.03.2009
comment
К сожалению, enum означает константу манифеста. Тем не менее, D требует изменения только того, что явно нарушено, все остальное следует установленным нормам для алгольских языков. Я уверен, что если бы вы действительно старались изо всех сил, вы могли бы найти множество странных ключевых слов и синтаксиса, которые можно было бы сделать лучше, например, присваивание/равенство, возвращаемое значение, указанное перед именем функции, структура/агрегат и т. д. - person deft_code; 26.10.2010

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

person FeepingCreature    schedule 04.03.2009
comment
Но это желание предполагает, что у компилятора всегда есть все соответствующие исходники. - person larsivi; 04.03.2009
comment
Что, если вы хотите предоставить сторонним библиотекам доступ к этой константной переменной? Что, если это целый экземпляр класса, который был сделан константным? - person Marenz; 19.12.2009
comment
Обратите внимание, я сказал компилятор/*компоновщик*. Кроме того, D в любом случае должен иметь возможность видеть значение переменной во время компиляции (для сворачивания констант и других вещей), так что еще меньше смысла в физическом хранении ее где-то — в любой ситуации, когда это потребуется в любом случае нужен исходный код. (Я не знаю ни одного компилятора, который внутренне дизассемблирует объектный код из более раннего запуска) - person FeepingCreature; 31.12.2009

Настоящая цель синтаксического расширения enum для поддержки отдельных констант манифеста, насколько я понимаю, заключается в том, что Дон Клагстон, гуру шаблонов D, вытворял какие-то сумасшедшие вещи с шаблонами. Он продолжал сталкиваться с длительным временем сборки, нелепым использованием памяти компилятором и т. д., потому что компилятор продолжал создавать внутренние структуры данных для константных переменных. Одна ключевая особенность константных/неизменяемых переменных по сравнению с перечислениями заключается в том, что константные/неизменяемые переменные являются lvalue и могут иметь свой адрес. Это означает, что у компилятора есть дополнительные накладные расходы. Обычно это не имеет значения, но когда вы выполняете действительно сложные метапрограммы времени компиляции, даже если константные переменные не оптимизированы, это все равно приводит к значительным накладным расходам во время компиляции.

person dsimcha    schedule 04.03.2009

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

Это похоже на разницу между const и readonly в C#. Первый является константой времени компиляции, а второй - константой времени выполнения. Это определенно повлияло на управление версиями сборок (поскольку сборки, ссылающиеся на только для чтения, получат копию во время компиляции и не получат изменения значения, если сборка, на которую ссылаются, будет перестроена с другим значением).

person chrish    schedule 04.03.2009