Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> define или const? 
V
    Опции темы
xTr1m
Дата 15.2.2010, 13:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 692
Регистрация: 9.2.2005
Где: Москва

Репутация: 1
Всего: 1



Доброго времени суток, хотелось бы узнать, что предпочтительнее использовать и почему?
Код

#define VARIABLE 100
const int VARIABLE = 100;

Заранее благодарю за ликвидацию моей безграмотности =))
PM MAIL WWW ICQ   Вверх
mes
Дата 15.2.2010, 13:05 (ссылка) |    (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



const , a для нахождения ответа на вопрос "почему?" воспользуйтесь поиском
smile


--------------------
PM MAIL WWW   Вверх
azesmcar
Дата 15.2.2010, 13:08 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



const лучше, хотя бы потому, что макрос нельзя в неймспейс запихнуть.

в гугле полно информации
http://www.google.mu/search?q=define+vs+co...lient=firefox-a

PM   Вверх
SenkraD
Дата 15.2.2010, 13:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 933
Регистрация: 3.2.2006
Где: Украина::Киев

Репутация: 2
Всего: 23



Из Мейерса:
Цитата
Правило 2: Предпочитайте const, enum и inline 
использованию # define 
Это правило лучше было бы назвать «Компилятор предпочтительнее  
препроцессора», поскольку #define зачастую вообще не относят к языку C++. В этом 
и заключается проблема. Рассмотрим простой пример; попробуйте написать что- 
нибудь вроде: 
tdefine ASPECT_RATIO 1.653 
Символическое имя ASPECT_RATIO может так и остаться неизвестным 
компилятору или быть удалено препроцессором до того, как код поступит на  
обработку компилятору. Если это произойдет, то имя ASPECTRATIO не попадет 
в таблицу символов. Поэтому в ходе компиляции вы получите ошибку (в сообщении 
о ней будет упомянуто значение 1.653, а не ASPECTRATIO). Это вызовет  
путаницу. Если имя ASPECT_RATIO было определено в заголовочном файле, который  
писали не вы, то вы вообще не будете знать, откуда взялось значение 1.653, и на поиски 
ответа потратите много времени. Та же проблема может возникнуть и при отладке, 
поскольку выбранное вами имя будет отсутствовать в таблице символов. 
Решение состоит в замене макроса константой: 
const double AspectRatio = 1.653; // имена, записанные большими буквами, 
// обычно применяются для макросов, 
// поэтому мы решили его изменить 
Будучи языковой константой, AspectRatio видима компилятору и,  
естественно, помещается в таблицу символов. К тому же в случае использования  
константы с плавающей точкой (как в этом примере) генерируется более компактный код, 
чем при использовании #define. Дело в том, что препроцессор, слепо подставляя 
вместо макроса ASPECT_RATIO величину 1.653, создает множество копий 1.653 
в объектном коде, в то время как использование константы никогда не породит 
более одной копии этого значения. 
При замене #define константами нужно помнить о двух особых случаях.  
Первый касается константных указателей. Поскольку определения констант обычно 
помещаются в заголовочные файлы (где к ним получает доступ множество  
различных исходных файлов), важно, чтобы сам указатель был объявлен с ключевым 
словом const, в дополнение к объявлению const того, на что он указывает.  
Например, чтобы объявить в заголовочном файле константную строку типа char*, слово 
const нужно написать дважды: 
const char * const authorName = "Scott Meyers"; 
Более подробно о сущности и применений слова const, особенно в связке 
с указателями, см. в правиле 3. Но уже сейчас стоит напомнить, что объекты типа 
string обычно предпочтительнее своих прародителей - строк типа char *, поэтому 
authorName лучше определить так: 
const std::string authorName("Scott Meyers"); 
Второе замечание касается констант, объявляемых в составе класса. Чтобы 
ограничить область действия константы классом, необходимо сделать ее членом 
Правило 2 
класса, и чтобы гарантировать, что существует только одна копия константы,  
требуется сделать ее статическим членом: 
class GamePlayer ( 
private: 
static const int NumTurns = 5; // объявление константы 
int scores[NumTurns]; // использование константы 
To, что вы видите выше, - это объявление NumTurns, а не ее определение. 
Обычно C++ требует, чтобы вы представляли определение для всего, что  
используете, но объявленные в классе константы, которые являются статическими и  
имеют встроенный тип (то есть целые, символьные, булевские) - это исключение из 
правил. До тех пор пока вы не пытаетесь получить адрес такой константы, можете 
объявлять и использовать ее без предоставления определения. Если же вам  
нужно получить адрес либо если ваш компилятор настаивает на наличии  
определения, то можете написать что-то подобное: 
const int GamePlayer::NumTurns; // определение NumTurns; см. ниже, 
// почему не указывается значение 
Поместите этот код в файл реализации, а не в заголовочный файл. Поскольку 
начальное значение константы класса представлено там, где она объявлена (то 
есть NumTurns инициализировано значением 5 при объявлении), то в точке  
определения задавать начальное значение не требуется. 
Отметим, кстати, что нет возможности объявить в классе константу  
посредством #define, потому что #define не учитывает области действия. Как только 
макрос определен, он остается в силе для всей оставшейся части компилируемого 
кода (если только где-то ниже не встретится #undef). Это значит, что директива 
#define неприменима не только для объявления констант в классе, но вообще не 
может быть использована для обеспечения какой бы то ни было инкапсуляции, 
то есть придать смысл выражению «private #define>> невозможно. В то же время 
константные данные-члены могут быть инкапсулированы, примером может  
служить NumTurns. 
Старые компиляторы могут не поддерживать показанный выше синтаксис, 
так как в более ранних версиях языка было запрещено задавать значения  
статических членов класса во время объявления. Более того, инициализация в классе 
допускалась только для целых типов и для констант. Если вышеприведенный 
синтаксис не работает, то начальное значение следует задавать в определении: 
class CostEstimate { 
private: 
static const double FudgeFactor; // объявление статической константы 
... // класса — помешается в файл заголовка 
}; 
const double // определение статической константы 
CostEstimate::FudgeFactor = 1.35; // класса — помещается в файл реализации 
Обычно ничего больше и не требуется. Единственное исключение  
обнаруживается тогда, когда для компиляции класса необходима константа. Например, 
Приучайтесь к C++ 
при объявлении массива GamePlayer::scores компилятору нужно знать размер 
массива. Чтобы работать с компилятором, ошибочно запрещающим  
инициализировать статические целые константы внутри класса, можно воспользоваться  
способом, известным под названием «трюка с перечислением».Он основан на том, 
что переменные перечисляемого типа можно использовать там, где ожидаются 
значения типа int, поэтому GamePlayer можно определить так: 
class GamePlayer { 
private: 
enum ( NumTurns = 5 }; // "трюк с перечислением" — делает из 
// NumTurns символ со значением 5 
int scores[NumTurns]; // нормально 
Этот прием стоит знать по нескольким причинам. Во-первых, поведение 
«трюка с перечислением» в некоторых отношениях более похоже на #define, чем 
на константу, а иногда это как раз то, что нужно. Например, можно получить  
адрес константы, но нельзя получить адрес перечисления, как нельзя получить и 
адрес #define. Если вы хотите запретить получать адрес или ссылку на какую- 
нибудь целую константу, то применение enum - хороший способ наложить такое 
ограничение. (Подробнее о поддержке проектных ограничений с помощью  
приемов кодирования можно узнать из правила 18). К тому же, хотя хорошие  
компиляторы не выделяют память для константных объектов целых типов (если только 
вы не создаете указателя или ссылки на объект), менее изощренные могут так 
поступать, а вам это, возможно, ни к чему. Как и #define, перечисления никогда не 
станут причиной подобного нежелательного распределения памяти. 
Вторая причина знать о «трюке с перечислением» чисто прагматическая. Он 
используется в очень многих программах, поэтому нужно уметь распознавать 
этот трюк, когда вы с ним сталкиваетесь. Вообще говоря, этот прием -  
фундаментальная техника, применяемая при метапрограммировании шаблонов (см. 
правило 48). 
Вернемся к препроцессору. Другой частый случай неправильного  
использования директивы #define - создание макросов, которые выглядят как функции, 
но не обременены накладными расходов, связанными с вызовом функций. Ниже 
представлен макрос, который вызывает некоторую функцию i с аргументом,  
равным максимальному из двух значений: 
// вызвать f, передав ей максимум из а и b 
«define CALL_WITH_MAX(a,b) f((a) > (b) ? (a) : (b)) 
В этой строчке содержится так много недостатков, что даже не совсем  
понятно, с какого начать. 
Всякий раз при написании подобного макроса вы должны помнить о том, что 
все аргументы следует заключать в скобки. В противном случае вы рискуете 
столкнуться с проблемой, когда кто-нибудь вызовет его с выражением в качестве 
аргумента. Но даже если вы сделаете все правильно, посмотрите, какие странные 
вещи могут произойти: 
Правило 3 
int a = 5, b = 0; 
CALL_WITH_MAX(++a, b) ; // a увеличивается дважды 
CALL_WITH_MAX(++a, b+10) ; // а увеличивается один раз 
Происходящее внутри max зависит от того, с чем она сравнивается! 
К счастью, вы нет нужды мириться с поведением, так сильно противоречащим 
привычной логике. Существует метод, позволяющий добиться такой же  
эффективности, как при использовании препроцессора. Но при этом обеспечивается как 
предсказуемость поведения, так и контроль типов аргументов (что характерно для 
обычных функций). Этот результат достигается применением шаблона  
встроенной (inline) функции (см. правило 30): 
template <typename T> 
inline void callWithMax(const TS a, const TS b) // Поскольку мы не знаем, 
{ // что есть Т, то передаем 
f(a > b ? a : b); // его по ссылке на const - 
} // см. параграф 20 
Этот шаблон генерирует целое семейство функций, каждая из которых  
принимает два аргумента одного и того же типа и вызывает f с наибольшим из них. 
Нет необходимости заключать параметры в скобки внутри тела функции, не  
нужно заботиться о многократном вычислении параметров и т. д. Более того,  
поскольку callWithMax - настоящая функция, на нее распространяются правила 
областей действия и контроля доступа. Например, можно говорить о встроенной 
функции, являющейся закрытым членом класса. Описать нечто подобное с  
помощью макроса невозможно. 
Наличие const, enum и inline резко снижает потребность в препроцессоре 
(особенно это относится к #define), но не устраняет ее полностью. Директива 
#include остается существенной, a #ifdef/#ifndef продолжают играть важную 
роль в управлении компиляцией. Пока еще не время отказываться от  
препроцессора, но определенно стоит задуматься, как избавиться от него в  
дальнейшем. 
Что следует помнить 
0 Для простых констант директиве #define следует предпочесть  
константные объекты и перечисления (enum). 
И Вместо имитирующих функции макросов, определенных через #define, 
лучше применять встроенные функции
P.S. Сори на прохое форматирование текста и местами неверные символы - копировал с djvu


--------------------
 Имеющий язык - да не убоится спросить! 
user posted image
PM MAIL ICQ   Вверх
kemiisto
Дата 15.2.2010, 13:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Дикий Кот. =^.^=
****
Награды: 1



Профиль
Группа: Участник Клуба
Сообщений: 3292
Регистрация: 29.7.2007

Репутация: 2
Всего: 160





--------------------
PM MAIL WWW GTalk Jabber   Вверх
artsb
Дата 15.2.2010, 13:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2280
Регистрация: 17.7.2007
Где: центр Вселенной

Репутация: 1
Всего: 64



Ещё: define vs const
И ещё: const лучше, чем define

Это сообщение отредактировал(а) artsb - 15.2.2010, 13:20


--------------------
Чем отличается умный человек от мудрого?
Умный - выпутается из любой ситуации.
Мудрый - просто в неё не попадёт.
PM MAIL   Вверх
xTr1m
Дата 15.2.2010, 13:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 692
Регистрация: 9.2.2005
Где: Москва

Репутация: 1
Всего: 1



Ох, спасибо.
PM MAIL WWW ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0514 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.