Должен ли я использовать #define, enum или const?

Из журнала изменений Python 3.0,

Модули StringIO и cStringIO исчезли. Вместо этого импортируйте модуль io и используйте io.StringIO или io.BytesIO для текста и данных соответственно.

blockquote>

Из документации по электронной почте Python 3 можно видеть, что вместо io.StringIO следует использовать :

from io import StringIO
from email.generator import Generator
fp = StringIO()
g = Generator(fp, mangle_from_=True, maxheaderlen=60)
g.flatten(msg)
text = fp.getvalue()

Ссылка: https://docs.python.org/3.4/library/io.html

122
задан Thom Wiggers 26 July 2015 в 22:37
поделиться

14 ответов

Объедините стратегии уменьшить недостатки единственного подхода. Я работаю во встроенных системах, таким образом, следующее решение основано на том, что целочисленные и побитовые операторы являются быстрой, низкой памятью & низко в использовании флэш-памяти.

Место перечисление в пространстве имен, чтобы препятствовать тому, чтобы константы загрязнили глобальное пространство имен.

namespace RecordType {

перечисление объявляет и определяет время компиляции, проверенное введенный. Всегда используйте проверку типа времени компиляции для проверки, аргументам и переменным дают корректный тип. Нет никакой потребности в определении типа в C++.

enum TRecordType { xNew = 1, xDeleted = 2, xModified = 4, xExisting = 8,

Создают другого участника для недопустимого состояния. Это может быть полезно как код ошибки; например, когда Вы хотите возвратить состояние, но операционные сбои ввода-вывода. Это также полезно для отладки; используйте его в списках инициализации и деструкторах, чтобы знать, должно ли значение переменной использоваться.

xInvalid = 16 };

Полагают, что у Вас есть две цели для этого типа. Отследить текущее состояние записи и создать маску для выбора записей в определенных состояниях. Создайте подставляемую функцию, чтобы протестировать, если значение типа допустимо для Вашей цели; как маркер состояния по сравнению с маской состояния. Это поймает ошибки, как эти typedef просто int и значение такой, как 0xDEADBEEF может быть в Вашей переменной через неинициализированные или mispointed переменные.

inline bool IsValidState( TRecordType v) {
    switch(v) { case xNew: case xDeleted: case xModified: case xExisting: return true; }
    return false;
}

 inline bool IsValidMask( TRecordType v) {
    return v >= xNew  && v < xInvalid ;
}

Добавляют using директива, если Вы хотите использовать тип часто.

using RecordType ::TRecordType ;

функции проверки значения полезны в, утверждает для захвата плохих значений, как только они используются. Чем более быстрый Вы ловите ошибка при выполнении, тем меньше ущерба она может нанести.

Вот некоторые примеры для соединения всего этого.

void showRecords(TRecordType mask) {
    assert(RecordType::IsValidMask(mask));
    // do stuff;
}

void wombleRecord(TRecord rec, TRecordType state) {
    assert(RecordType::IsValidState(state));
    if (RecordType ::xNew) {
    // ...
} in runtime

TRecordType updateRecord(TRecord rec, TRecordType newstate) {
    assert(RecordType::IsValidState(newstate));
    //...
    if (! access_was_successful) return RecordType ::xInvalid;
    return newstate;
}

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

86
ответ дан Benjamin 26 July 2015 в 22:37
поделиться

Я пошел бы с

typedef enum { xNew = 1, xDeleted, xModified = 4, xExisting = 8 } RecordType;

Просто потому что:

  1. Это более чисто, и это делает код читаемым и удобным в сопровождении.
  2. Это логически группирует константы.
  3. время Программиста более важно, если Ваше задание не для сохранения тех 3 байтов.
0
ответ дан Vivek 26 July 2015 в 22:37
поделиться

Не то, чтобы мне нравится сверхпроектировать все, но иногда в этих случаях может стоить создать (маленький) класс для инкапсуляции этой информации. При создании класса RecordType затем, он мог бы иметь функции как:

пустой setDeleted ();

пустой clearDeleted ();

bool isDeleted ();

и т.д.... (или безотносительно исков конвенции)

Это могло проверить комбинации (в случае, где не все комбинации являются допустимыми, например, если 'новый' и 'удаленный' не мог бы оба быть установлен одновременно). Если бы Вы просто использовали битовые маски и т.д. затем код, который устанавливает состояние, то должен проверить, класс может инкапсулировать ту логику также.

класс может также дать Вам способность присоединить значимую информацию о входе к каждому состоянию, Вы могли добавить функцию для возврата строкового представления текущего состояния и т.д. (или использовать операторы потоковой передачи '< <';).

Для всего этого, если Вы волнуетесь по поводу устройства хранения данных, что у Вас мог бы все еще быть класс только, имеют 'символьный' элемент данных, поэтому только возьмите небольшое количество устройства хранения данных (предполагающий, что это не является виртуальным). Конечно, в зависимости от аппаратных средств и т.д. у Вас могут быть проблемы выравнивания.

у Вас могли быть фактические битовые значения, не видимые к остальной части 'мира', если они находятся в анонимном пространстве имен в cpp файле, а не в заголовочном файле.

, Если Вы находите, что код с помощью enum/#define/битовой маски и т.д. имеет много кода 'поддержки' для контакта с недопустимыми комбинациями, регистрируя и т.д. затем инкапсуляцию в классе, может быть достойным рассмотрения. Конечно, большинство раз простые проблемы более обеспечены с простыми решениями...

0
ответ дан Benjamin 26 July 2015 в 22:37
поделиться

При использовании QT, необходимо взглянуть для QFlags. Класс QFlags обеспечивает безопасный с точки зрения типов способ сохранить ИЛИ-КОМБИНАЦИИ перечислимых значений.

2
ответ дан Thomas Koschel 26 July 2015 в 22:37
поделиться

Если Вы хотите безопасность типов классов, с удобством синтаксиса перечисления и разрядной проверки, рассматриваете Безопасные Маркировки в C++ . Я работал с автором, и он довольно умен.

Остерегаются, все же. В конце этот пакет использует шаблоны и макросы!

3
ответ дан Don Wakefield 26 July 2015 в 22:37
поделиться

Я, вероятно, не использовал бы перечисление для этого своего рода вещь, где значения могут быть объединены вместе, более обычно перечисления являются взаимоисключающими состояниями.

, Но какой бы ни метод Вы используете, для создания этого более ясным, что это значения, которые являются битами, которые могут быть объединены вместе, используйте этот синтаксис для фактических значений вместо этого:

#define X_NEW      (1 << 0)
#define X_DELETED  (1 << 1)
#define X_MODIFIED (1 << 2)
#define X_EXISTING (1 << 3)

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

2
ответ дан 26 July 2015 в 22:37
поделиться

На основе KISS, высокосвязная и слабая связь , задает эти вопросы -

  • , Кто должен знать? мой класс, моя библиотека, другие классы, другие библиотеки, третьи стороны
  • , Что уровень абстракции я должен обеспечить? Делает потребителя, понимают битовые операции.
  • Будет я иметь, должны взаимодействовать через интерфейс от VB/C# и т.д.?

существует замечательная книга" Крупномасштабная Разработка программного обеспечения C++ ", это способствует базовым типам внешне, если можно избежать другого заголовочного файла / интерфейсная зависимость, необходимо попытаться.

2
ответ дан titanae 26 July 2015 в 22:37
поделиться

Необходимо ли на самом деле раздать флаговые значения как концептуальное целое, или Вы собираетесь иметь много кода на флаг? Так или иначе я думаю, имея это как класс, или структура 1-разрядных битовых полей могла бы на самом деле быть более ясной:

struct RecordFlag {
    unsigned isnew:1, isdeleted:1, ismodified:1, isexisting:1;
};

Затем Ваш рекордный класс мог иметь структуру переменная члена RecordFlag, функции могут взять аргументы структуры типа RecordFlag и т.д. Компилятор должен упаковать битовые поля вместе, оставив свободное место.

2
ответ дан wnoise 26 July 2015 в 22:37
поделиться

Вот несколько статей о константе по сравнению с макросами по сравнению с перечислениями:

Символьные константы
Константы Перечисления по сравнению с Постоянными Объектами

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

8
ответ дан xiterion 26 July 2015 в 22:37
поделиться

Перечисления были бы более соответствующими, поскольку они предоставляют "значение идентификаторам", а также безопасности типов. Можно ясно сказать, что "xDeleted" имеет "RecordType" и которые представляют "тип записи" (ничего себе!) даже после лет. Consts потребовал бы комментариев для этого, также они потребуют движения вверх и вниз в коде.

4
ответ дан 2 revs, 2 users 67% 26 July 2015 в 22:37
поделиться

Если возможно НЕ используйте макросы. Ими не очень восхищаются когда дело доходит до современного C++.

5
ответ дан INS 26 July 2015 в 22:37
поделиться

Даже если необходимо использовать 4 байта для хранения перечисления (я не настолько знаком с C++ - я знаю, что можно указать базовый тип в C#), это все еще стоит того - используют перечисления.

В этот день и возраст серверов с ГБ памяти, вещи как 4 байта по сравнению с 1 байтом памяти на прикладном уровне в целом не имеют значения. Конечно, если в Вашей конкретной ситуации, использование памяти настолько важно (и Вы не можете заставить C++ использовать байт для поддержки перечисления), затем можно считать 'статическую константу' маршрутом.

В конце дня, необходимо ли спросить себя, действительно ли это стоит хита обслуживания использования 'статической константы' для 3 байтов сбережений памяти для Вашей структуры данных?

Что-то еще для учета - IIRC, на x86, структуры данных составляют выровненные 4 байта, поэтому если у Вас нет многих элементов ширины байта в Вашей 'рекордной' структуре, он не мог бы на самом деле иметь значения. Протестируйте и удостоверьтесь, что это делает перед созданием компромисса в пригодности для обслуживания для производительности/пространства.

3
ответ дан Jonathan Rupp 26 July 2015 в 22:37
поделиться
  • 1
    Я имею в виду альфа-компонент backgroundColor свойство UIView, мы говорим о:) I' ve не говорил о вложенных представлениях вообще! – deanWombourne 29 December 2012 в 20:20

Исключите Вас станд.:: bitset? Наборы флагов - то, для чего это. Сделайте

typedef std::bitset<4> RecordType;

затем

static const RecordType xNew(1);
static const RecordType xDeleted(2);
static const RecordType xModified(4);
static const RecordType xExisting(8);

, поскольку существует набор перегрузок оператора для bitset, можно теперь сделать

RecordType rt = whatever;      // unsigned long or RecordType expression
rt |= xNew;                    // set 
rt &= ~xDeleted;               // clear 
if ((rt & xModified) != 0) ... // test

Или что-то очень похожее на это - я ценил бы любые исправления, так как я не протестировал это. Можно также обратиться к битам индексом, но обычно лучше определить только один набор констант, и константы RecordType, вероятно, более полезны.

Принятие Вы исключили bitset, я голосую за перечисление .

я не покупаю тот кастинг перечислений, серьезный недостаток - хорошо, таким образом, это является немного шумным, и присвоение значения из диапазона к перечислению является неопределенным поведением, таким образом, теоретически возможно выстрелить себе в ногу на некоторых необычных реализациях C++. Но если Вы только делаете это, когда необходимый (который является при движении от интервала до перечисления iirc), это - совершенно нормальный код, который люди видели прежде.

я сомнителен о любой стоимости пространства перечисления, также. переменные uint8 и параметры, вероятно, не будут использовать никого меньше стека, чем ints, поэтому только устройство хранения данных в вопросах классов. Существуют некоторые случаи, где упаковка нескольких байтов в структуре победит (в этом случае, можно бросить перечисления в и из uint8 устройства хранения данных), но обычно дополнение уничтожит преимущество во всяком случае.

, Таким образом, перечисление не имеет никаких недостатков по сравнению с другими, и поскольку преимущество дает Вам немного безопасности типов (Вы не можете присвоить некоторое случайное целочисленное значение, явно не бросая), и очевидные способы обращения ко всему.

Для предпочтения я также поместил "= 2" в перечислении, между прочим. Это не необходимо, но "принцип наименьшего количества удивления" предлагает, чтобы все 4 определения выглядели одинаково.

30
ответ дан Steve Jessop 26 July 2015 в 22:37
поделиться

Забудьте определение

, Они загрязнят Ваш код.

битовые поля?

struct RecordFlag {
    unsigned isnew:1, isdeleted:1, ismodified:1, isexisting:1;
};

никогда не используют это . Вы более обеспокоены скоростью, чем с экономией 4 ints. Используя битовые поля на самом деле медленнее, чем доступ к любому другому типу.

Однако у разрядных участников в структурах есть практические недостатки. Во-первых, упорядочивание битов в памяти варьируется от компилятора до компилятора. Кроме того, много популярных компиляторов генерируют неэффективный код для чтения, и запись укусила участников , и существует потенциально серьезно проблемы потокобезопасности касающийся битовых полей (особенно в многопроцессорных системах) вследствие того, что большинство машин не может управлять произвольными наборами битов в памяти, но должно вместо этого загрузить и сохранить целые слова. например, следующее не было бы ориентировано на многопотоковое исполнение, несмотря на использование взаимного исключения

Источник: http://en.wikipedia.org/wiki/Bit_field :

И если Вам нужно больше причин для [1 135] не битовые поля использования, возможно , Raymond Chen убедит Вас в его Старая Новая Вещь Сообщение: анализ рентабельности битовых полей для набора булевских переменных в [1 111] http://blogs.msdn.com/oldnewthing/archive/2008/11/26/9143050.aspx

интервал константы?

namespace RecordType {
    static const uint8 xNew = 1;
    static const uint8 xDeleted = 2;
    static const uint8 xModified = 4;
    static const uint8 xExisting = 8;
}

Помещение их в пространстве имен прохладно. Если они будут объявлены в Вашем CPP или заголовочном файле, то их значения будут встроены. Вы сможете использовать, включают те значения, но это немного увеличит связь.

А-ч, да: удаляют статическое ключевое слово . статичный удерживается от использования в C++ при использовании, как Вы делаете, и если uint8 будет типом здания, то Вам не будет нужно это для объявления этого в заголовке, включенном многочисленными источниками того же модуля. В конце код должен быть:

namespace RecordType {
    const uint8 xNew = 1;
    const uint8 xDeleted = 2;
    const uint8 xModified = 4;
    const uint8 xExisting = 8;
}

проблема этого подхода состоит в том, что Ваш код знает значение Ваших констант, которое увеличивает немного связь.

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

то же как интервал константы, с несколько более сильным вводом.

typedef enum { xNew = 1, xDeleted, xModified = 4, xExisting = 8 } RecordType;

Они все еще загрязняют глобальное пространство имен, все же. Между прочим... Удаляют определение типа . Вы работаете в C++. Те определения типов перечислений и структур загрязняют код больше, чем что-либо еще.

результат отчасти:

enum RecordType { xNew = 1, xDeleted, xModified = 4, xExisting = 8 } ;

void doSomething(RecordType p_eMyEnum)
{
   if(p_eMyEnum == xNew)
   {
       // etc.
   }
}

, Как Вы видите, Ваше перечисление загрязняет глобальное пространство имен. При помещении этого перечисления в пространство имен у Вас будет что-то как:

namespace RecordType {
   enum Value { xNew = 1, xDeleted, xModified = 4, xExisting = 8 } ;
}

void doSomething(RecordType::Value p_eMyEnum)
{
   if(p_eMyEnum == RecordType::xNew)
   {
       // etc.
   }
}

интервал константы экстерна?

, Если Вы хотите уменьшить связь (т.е. способность скрыть значения констант, и таким образом, измените их, как желаемый, не нуждаясь в полной перекомпиляции), можно объявить ints как экстерн в заголовке, и столь же постоянный в файле CPP, как в следующем примере:

// Header.hpp
namespace RecordType {
    extern const uint8 xNew ;
    extern const uint8 xDeleted ;
    extern const uint8 xModified ;
    extern const uint8 xExisting ;
}

И:

// Source.hpp
namespace RecordType {
    const uint8 xNew = 1;
    const uint8 xDeleted = 2;
    const uint8 xModified = 4;
    const uint8 xExisting = 8;
}

Вы не сможете использовать, включают те константы, все же. Таким образом в конце, выберите свой яд... :-p

54
ответ дан Izhaki 26 July 2015 в 22:37
поделиться
  • 1
    Я думаю, что Вы имеете в виду фон color' s альфа 0.25, не фон view' s. Я предполагаю, что фоновое представление и цвет фона являются двумя разными вещами. – Philip007 26 December 2012 в 17:37
Другие вопросы по тегам:

Похожие вопросы: