2013-03-05 3 views
2

Для некоторых видов программ мне нужно использовать постоянное высокое значение, чтобы указать некоторые свойства некоторых переменных. Я имею в виду let color[i] = 1000000;, если узел i в дереве не исследован. Но я довольно часто miswrite число 0s в конце, так что я просто задавался вопросом, является ли это лучше сделать это таким образом:Должен ли я избегать использования #define в C++? Почему и какие альтернативы я могу использовать?

#define UNEXPLORED 1000000; 
color[i] = UNEXPLORED; 

Я помню, что где-то я читал, что это гораздо лучше, чтобы избежать использования #define , Это правильно? Как бы вы справились с этой проблемой?

+3

Пройдите эту тему. Лучший ответ оттуда - '# define's' не относятся к сфере видимости - http://stackoverflow.com/questions/1944041/advantage-and-disadvantages-of-defines-vs-constants –

ответ

3

Для простых констант, вы можете использовать либо const или новый constexpr:

constexpr unsigned int UNEXPLORED = 1000000; 

В таком случае, как это, нет никакой разницы между использованием const и constexpr. Однако «переменные» с пометкой constexpr оцениваются во время компиляции, а не во время выполнения, и могут использоваться в тех местах, которые в противном случае принимают только литералы.

+1

Есть ли какая-то особая причина для использования' auto' здесь «Основное использование, которое я вижу в« auto », заключается в том, чтобы избежать повторения имен типов или формулировки сложных, вложенных типов. Это не так, и явно указывая, что тип здесь улучшает ясность. (Аналогично, почему' constexpr', а не традиционный 'const'?) –

+1

@JamesKanze - использование 'auto' здесь приведет к созданию целочисленного типа, достаточно большого для хранения фактического значения. 'unsigned int' не обязательно достаточно велик, чтобы содержать' 1000000', проблему, которой не обладает макрос. –

+0

@PeteBecker Это интересный аспект, о котором я не думал. В зависимости от контекста это может считаться недостатком или преимуществом. (Я предполагаю, что если '1000000' не вписывался в' unsigned int', компилятор будет хотя бы предупреждать.) –

2

Например, используйте константы.

const unsigned int UNEXPLORED = 1000000; 

или перечисления

enum { UNEXPLORED = 1000000 }; 
+0

Это становится все более странным для меня. :(Я пытаюсь узнать конкретную часть, а затем приходить тысячи других. :(В чем разница между ENUM и STRUCT? Что нужно использовать для чего? – gen

+0

@gen Для таких вопросов я бы предложил вам захватить [хороший книга] (http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list), чтобы вести ваше обучение. – Angew

+0

@ Ангелое Большое спасибо, действительно, неплохо :) – gen

0

При использовании констант два ответа выше правильны, однако #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 s для констант как особый вид макроса.

С помощью макросов вы также можете передавать параметры, и это особенно полезно для обеспечения соблюдения правил ведения журнала/исключений по коду. Например

#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 символов не существует, и поэтому их нельзя увидеть в отладчике. Они также могут сбивать с толку, если вы получаете ошибки компиляции, особенно если они являются длинными макросами.

Смежные вопросы