Подтвердить что ты не робот

Использование переменной статической константы С++

Скажем, что у меня есть класс, для которого требуется несколько констант. Некоторые функции-члены требуют использования этих констант. Использование #define неодобрительно, поскольку это может вызвать конфликты. Константы представляют собой шестнадцатеричные шаблоны из 8 или 16 бит и сохраняются как uint8_t или uint16_t. Эти константы также не меняются от экземпляра к экземпляру класса, и поэтому память (хотя и очень маленькая память) может быть сохранена, имея только одну копию констант.

Есть ли что-то неправильное или, возможно, лучший способ выполнить выше, а не просто делать что-то вроде следующего:

// mycode.h
// .......
class myclass {
private:
  static const uint16_t kMyClassConstant_ = 0xBEEF;
// .......
};

Заранее благодарим за помощь.

4b9b3361

Ответ 1

Учитывая ваше описание ситуации, я бы сказал, что использование static const - это хороший подход. В С++ 11 вы можете изменить его на static constexpr, чтобы подчеркнуть его константу времени компиляции, хотя в результате этого ничего не изменится.

Если вы ссылаетесь на myclass::kMyClassContant_ где-то в коде таким образом, который имеет отношение к правилу с одним определением (odr), esp. в контекстах, требующих ссылки (включая const-reference), компилятор будет жаловаться на отсутствие определения константы. В этом случае недостаточно объявить и инициализировать его внутри класса. Это может заставить вас отделить объявление и определение:

// mycode.h
class myclass {
private:
  static const uint16_t kMyClassConstant_;
};

// mycode.cpp
const uint16_t myclass::kMyClassConstant_ = 0xBEEF;

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

// mycode.h
class myclass {
private:
  static constexpr uint16_t kMyClassConstant_()
  { return 0xBEEF; }
};

Это правильная работа для многих проблем, связанных с odr, и это не приводит к потере производительности. Является ли это действительно полезным, зависит от того, сколько издержек состоит в том, чтобы поддерживать отдельные декларации и определения обычной статической константы. Если вы ожидаете, что ваши константы никогда не будут меняться по мере развития вашего кода, предпочтительнее использовать обычные статические константы с отдельными определениями. Но если вы часто изменяете определения констант, необходимо повторно скомпилировать файл определения и перенастроить его во все соответствующие части проекта, вы можете подумать над предлагаемым выше решением на основе функций в качестве лучшей альтернативы.

Последний комментарий к типу данных: принудительное его использование в 16 бит с использованием std::uint16_t может оказаться полезным, если вам нужно хранить много этих значений в компактной форме. В противном случае фактический размер может не иметь особого значения, и в этом случае std::uint_fast16_t (который может быть больше 16 бит) может быть лучше.

Ответ 2

Вы можете использовать свойства типа, чтобы реализовать это:

#include <type_traits>

class myclass {
private:
  typedef std::integral_constant<uint16_t , 0xBEEF> kMyClassConstant;

  // ...
};

используется как myclass::kMyClassConstant::value.

Это показывает цель реализации интегральной константы и предотвращает случайное использование адреса константы.