Я пытаюсь реализовать облегченную карту, просто используя массив элементов, членами которых являются ключ и значение. Содержимое карты известно во время компиляции, поэтому я думаю об использовании массива фиксированного размера следующим образом:
#include "stdafx.h"#include <string>
// class Item is declared in file1.h. Definition could be in file1.cpp.
class Item
{
public:
Item(const std::string name) : m_name(name) {}
const std::string GetName() const { return m_name; }
private:
const std::string m_name;
};
// The static consts are declared in file2.h which includes file1.h.
static const Item ITEM1 = std::string("Item1");
static const Item ITEM2 = std::string("Item2");
static const Item ITEM3 = std::string("Item3");
static const Item ITEM4 = std::string("Item4");
// ItemMapEntry and ItemMapUser is defined in file3.h...
struct ItemMapEntry
{
const Item& key;
const Item& value;
};
class ItemMapUser
{
public:
void Run();
private:
static const ItemMapEntry map[];
};
// and declared in file3.cpp which includes file2.h.
const ItemMapEntry ItemMapUser::map[] =
{
{ ITEM1, ITEM2 },
{ ITEM3, ITEM4 }
};
void ItemMapUser::Run()
{
for (int i = 0; i < (sizeof(map) / sizeof(map[0])); i++)
{
printf("%s %s\n", map[i].key.GetName().c_str(), map[i].value.GetName().c_str());
}
}
// main.cpp includes file3.h.
int main()
{
ItemMapUser itemMapUser;
itemMapUser.Run();
}
Теперь мой вопрос: фрагмент кода работает, как и предполагалось, но у меня почему-то возникает ощущение, что я полагаюсь на порядок инициализации, чтобы инициализировать их содержимое от ITEM1 до ITEM4 перед их использованием в ItemMapUser :: map. Я просмотрел много вопросов, относящихся к этой теме (особенно те, которые имели тег static-order-fiasco), но не смог найти ни одного, связанного с использованием массивов.
const Item anotherItem = ITEM1;
например?Ты используешь ItemMapUser::map
в коде, который можно вызвать из
конструктор статического объекта? Нет проблем
инициализация ссылок с неструктурированными объектами, но
будет, если вы используете их до того, как объект будет построен.
Re ваши вопросы:
Нет, если вы на самом деле не используете объекты ссылки
обозначить в конструкторе статический объект.
В основном, тот факт, что это ссылки, и вы можете
безопасно инициализировать референ с неструктурированным объектом.
(Существуют определенные ограничения при наследовании,
но они не кажутся здесь уместными.)
Это не имеет ничего общего с тем, инициализируете ли вы
объект или массив. Если вы инициализируете объект
(член массива или нет), а не ссылка, и вызов
конструктор копирования, копируемый объект лучше
построен. Что вы можете гарантировать, только если это определено в
тот же переводчик.
Я бы сказал, что да, вы можете столкнуться с фиаско статического порядка инициализации.
Причина, по которой вы еще не сталкивались с этим, заключается в том, что приложение еще не стало достаточно сложным для создания циклической статической инициализации.
Я не думаю, что использование массива имеет какое-либо значение.
Во всяком случае, это не стоит рисковать. Я бы начал со следующего паттерна и развивал его по мере необходимости, то есть создавая статический класс или любой другой, который лучше всего соответствует вашим целям.
#include <iostream>
#include <string>
#include <map>
using namespace std;// Define safely in any module and use safely from any module.
// With C++11 use of an initializer list could eliminate the init statement.
// If you want to define the constants separately from the map use of constexpr
// should preclude any initialization order issues.
static const map<string, string>& Map()
{
static map<string, string> map;
static bool init = false;
if(!init)
{
map["Item1"] = "Item2";
map["Item3"] = "Item4";
init = true;
}
return map;
}int main()
{
cout << "Hello world!";
}
Может быть, вопрос был упрощен в ходе опроса, но здесь происходит очень много раздумий из-за чего-то, что в основном намного проще.
struct entry {
const char *key;
const char *value;
};
entry data_map[] = {
"Item1", "Item2",
"Item3", "Item4",
0, 0
};
for (entry *current = data_map; current->key != 0; ++current)
printf("%s %s\n", current->key, current->value);