Принудительная инициализация статического члена - PullRequest
2 голосов
/ 01 ноября 2011

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

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

class MyClass
{
  static MapType s_myMap;
public:
  static const MapType& getTheMap()
  {
    if (s_myMap.empty())
    {
      // Populate the map
    }
    return s_myMap;
  }
};

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

Чтобы решить эту проблему, я думаю сделать карту локальной для метода получения:

class MyClass
{
public:
  static const MapType& getTheMap()
  {
    static MapType s_myMap;
    if (s_myMap.empty())
    {
      // Populate the map
    }
    return s_myMap;
  }
};

Это хорошая идея, или есть лучший способ добиться этого?

Ответы [ 4 ]

1 голос
/ 01 ноября 2011

Если MyClass::getTheMap() не вызывается в глобальной области видимости / namespace, вам не нужно беспокоиться об использовании элемента данных static до его инициализации.

Однако, если в глобальной области действия / namespace используется вышеуказанный метод static getTheMap():

SomeGlobal object = MyClass::getTheMap();

тогда ваш нынешний подход кажется нормальным.

1 голос
/ 01 ноября 2011

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

Что касается его инициализации, я часто использую конструктор с двумя итераторами, поэтому что я могу сделать саму карту постоянной. Для этого просто определите struct с оператором преобразования, что-то вроде:

struct MapInitData
{
    char const* key;      //  Or whatever type is needed.
    char const* value;    //  Or whatever type is needed.
    operator MapType::value_type() const
    {
        return MapType::value_type( key, value );
    }
};

MapInitData const mapInitTable[] =
{
    { "key1", "value1" },
    //  ...
};

MapType const ourMap( begin( mapInitTable ), end( mapInitTable ) );
1 голос
/ 01 ноября 2011

Вы можете объявить класс для этой коллекции и заполнить его в конструкторе.

0 голосов
/ 01 ноября 2011

ваша функция 'getTheMap' должна иметь блокировку для безопасности потока. Хорошей идеей будет переместить ее локально в функцию.

Я думаю, что это связано со статьей drdobbs "C ++ и опасности двойной проверки блокировки" http://drdobbs.com/cpp/184405726 аналогично вопросу. Здесь он рассматривает варианты использования и безопасность различных типов одноэлементных и других шаблонов с безопасностью потоков.

Что касается уничтожения, нужно ли его уничтожать?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...