Для некоторых видов программ мне нужно использовать постоянное высокое значение, чтобы указать некоторые свойства некоторых переменных. Я имею ввиду color[i] = 1000000;
если i
узел в дереве неисследован. Но я довольно часто неправильно пишу число 0 в конце, поэтому я просто удивился, лучше ли это делать так:
#define UNEXPLORED 1000000;
color[i] = UNEXPLORED;
Я помню, что где-то я читал, что лучше избегать использования #define. Это правильно? Как бы вы решили эту проблему?
Для простых констант вы можете использовать либо const
или новый constexpr
:
constexpr unsigned int UNEXPLORED = 1000000;
В таком случае нет разницы между const
а также constexpr
, Тем не менее, «переменные» отмечены constexpr
оцениваются во время компиляции, а не во время выполнения, и могут использоваться в местах, которые в противном случае принимают только литералы.
Например используйте константы.
const unsigned int UNEXPLORED = 1000000;
или перечисления
enum { UNEXPLORED = 1000000 };
При использовании констант два ответа выше верны, однако #define
не ограничивается только этим использованием. Еще один пример использования #define
это макросы.
макрос
Макросы — это части кода, используемые препроцессором, и они работают точно так же, как и другие #define
заявления на этот счет. Препроцессор буквально поменяет местами вхождение вашего определенного символа с кодом макроса. Пример:
#define HELLO_MAC do{ std::cout << "Hello World" << std::endl; }while(false)
int main(int argc, char** argv)
{
HELLO_MAC;
}
Это буквально поменяет HELLO_MAC
символ с кодом, который я объявил. Если бы это была константа, она бы сделала то же самое. Так что вы можете думать о #define
для констант как особого вида макросов.
С помощью макросов вы также можете передавать параметры, и это особенно полезно для применения политик ведения журналов / исключений над кодом.
Например
#define THROW_EXCEPT( ex_type, ex_msg ) /
do{ throw ex_type( buildExString( (ex_msg), __LINE__, __FILE__ ) ); }while(false)
...
// somewhere else
THROW_EXCEPT( std::runtime_error, "Unsupported operation in current state" );
Этот код позволяет мне гарантировать, что каждый регистрируется со строкой файла, который вызвал исключение.
Шаблоны часто являются лучшим выбором вместо макросов, но я не могу использовать функции шаблонов для этого примера, потому что мне нужно использовать __LINE__
а также __FILE__
функции с места броска, а не с места расположения функции шаблона.
Где вы не должны использовать макросы? В любом месте вы можете использовать что-то еще. Макросы, как и любой #define
предварительно обработаны, поэтому компилятор их вообще не видит. Это означает, что нет никаких символов, созданных для HELLO_MAC
или же THROW_EXCEPT
и поэтому их нельзя увидеть в отладчике. Они также могут сбивать с толку, если вы получаете ошибки компиляции, особенно если это длинные макросы.