Лучше ли использовать static const
vars, чем препроцессор #define
? Или, может быть, это зависит от контекста?
Каковы преимущества/недостатки для каждого метода?
Лучше ли использовать static const
vars, чем препроцессор #define
? Или, может быть, это зависит от контекста?
Каковы преимущества/недостатки для каждого метода?
Лично я ненавижу препроцессор, поэтому всегда буду идти со const.
Основное преимущество #define заключается в том, что он не требует сохранения памяти в вашей программе, так как он действительно просто заменяет некоторый текст буквенным значением. Это также имеет то преимущество, что у него нет типа, поэтому он может использоваться для любого целочисленного значения без генерирования предупреждений.
Преимущества "const" заключаются в том, что они могут быть ограничены, и их можно использовать в ситуациях, когда нужно передать указатель на объект.
Я точно не знаю, что вы получаете с "статической" частью. Если вы объявляете глобально, я бы поставил его в автономное пространство имен вместо использования static. Например
namespace {
unsigned const seconds_per_minute = 60;
};
int main (int argc; char *argv[]) {
...
}
Плюсы и минусы всего, в зависимости от использования:
enum class X
устраняются с помощью области X::
int
, но может быть явно задан программистомtemplate <typename T> void f(T t) { cout << ++t; }
не будет компилироваться, хотя вы можете обернуть enum в класс с неявным конструктором, оператором литья и определяемыми пользователем операторами)template <typename T> void f(T)
получает отдельный экземпляр, когда передается одно и то же числовое значение из разных перечислений, все из которых отличны от любого фактического экземпляра f(int)
. Каждый функциональный объектный код может быть идентичным (игнорируя смещения адресов), но я бы не ожидал, что компилятор/компоновщик устранит ненужные копии, хотя вы можете проверить свой компилятор/компоновщик, если вам это нравится.enum { A = 1, B = 2 }
- is A|B
"юридический" с точки зрения программной логики?)make
и другие инструменты перекомпиляции на основе временной метки будут приводить к перекомпиляции клиента, когда они 'изменено (плохо!)#define
ala #define S std::string("abc")
, но константа избегает повторного построения отдельных временных рядов в каждой точке использования.const
, которое минимизирует работу и воздействие при переключении между двумя#define X "x"
и некотором использовании клиента ala "pre" X "post"
, если вам нужно или нужно сделать X переменной, изменяемой во время выполнения, а не константой, вы принудительно редактируете код клиента (а не просто перекомпиляцию), тогда как этот переход проще с const char*
или const std::string
, поскольку они уже заставляют пользователя включать операции конкатенации (например, "pre" + X + "post"
для string
)sizeof
непосредственно в определенном числовом литералеunsigned
){ 1, 2 }
, которые могут использоваться для инициализации массивов или #define MICROSECONDS *1E-6
и т.д. (определенно не рекомендуя это!)__FILE__
и __LINE__
, могут быть включены в макроподстановку#if
для условного включения кода (более мощный, чем постпреобразование "если", поскольку код не нужно компилировать, если он не выбран препроцессором), используйте #undef
- ine, redefine и т.д.make
и другие инструменты перекомпиляции на основе временной метки вызовут перекомпиляцию клиента при их изменении (плохо!)Как правило, я использую const
и считаю их наиболее профессиональным вариантом для общего использования (хотя другие имеют простоту, привлекательную для этого старого ленивого программиста).
Если это вопрос на С++, и он упоминает #define
как альтернативу, то речь идет о константах "глобальный" (т.е. размер файла), а не о членах класса. Когда дело доходит до таких констант в С++ static const
, избыточно. В С++ const
есть внутренняя связь по умолчанию, и нет смысла объявлять их static
. Так что это действительно о const
vs. #define
.
И, наконец, в С++ const
предпочтительнее. По крайней мере, потому что такие константы напечатаны и скопированы. Просто нет причин предпочитать #define
над const
, за исключением нескольких исключений.
Строковые константы, BTW, являются одним из примеров такого исключения. Строковые константы #define
d можно использовать функцию компиляции времени компиляции компиляторов C/С++, как в
#define OUT_NAME "output"
#define LOG_EXT ".log"
#define TEXT_EXT ".txt"
const char *const log_file_name = OUT_NAME LOG_EXT;
const char *const text_file_name = OUT_NAME TEXT_EXT;
P.S. Опять же, на всякий случай, когда кто-то упоминает static const
как альтернативу #define
, обычно это означает, что они говорят о C, а не о С++. Интересно, правильно ли указан этот вопрос...
Использование static const похоже на использование любых других константных переменных в вашем коде. Это означает, что вы можете отслеживать, откуда приходит информация, в отличие от #define, который будет просто заменен в коде в процессе предварительной компиляции.
Возможно, вы захотите взглянуть на С++ FAQ Lite для этого вопроса: http://www.parashift.com/c++-faq-lite/newbie.html#faq-29.7
Обычно вы должны предпочесть статические константы. Это не имеет никакого недостатка. Пропроцессор должен в основном использоваться для условной компиляции (а иногда и для действительно грязных трюков).
Смотрите здесь: static const vs define
обычно объявление const (обратите внимание, что оно не обязательно должно быть статическим) - это путь
Определение констант с помощью директивы препроцессора #define
не рекомендуется применять не только в C++
, но и в C
. Эти константы не будут иметь тип. Даже в C
было предложено использовать const
для констант.
Если вы определяете константу, которая будет использоваться для всех экземпляров класса, используйте static const. Если константа специфична для каждого экземпляра, просто используйте const (но обратите внимание, что все конструкторы класса должны инициализировать эту переменную-член const в списке инициализации).
Всегда предпочитайте использовать языковые функции над некоторыми дополнительными инструментами, такими как препроцессор.
ES.31: Не используйте макросы для констант или "функций"
Макросы являются основным источником ошибок. Макросы не подчиняются обычным областям и правила типа. Макросы не подчиняются обычным правилам для аргументов прохождение. Макросы гарантируют, что человеческий читатель увидит что-то другое от того, что видит компилятор. Макрос осложняет создание инструмента.