0

我试图通过简单地使用其成员是键和值的元素数组来实现轻量级映射。地图内容在编译时是已知的,因此我考虑使用固定大小的数组,如下所示:

#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;如果我尝试使用例如初始化一个简单的变量会是什么样子?
4

3 回答 3

0

您是否ItemMapUser::map在可以从静态对象的构造函数中调用的代码中使用?用未构造的对象初始化引用没有问题,但是如果在构造对象之前使用它们就会有问题。

回复您的问题:

  1. 除非您在静态对象的构造函数中实际使用引用指定的对象,否则不会。

  2. 基本上,这些是引用的事实,您可以使用未构造的对象安全地初始化引用。(涉及继承时有一定的限制,但在这里似乎不相关。)

  3. 它与您是初始化对象还是数组无关。如果你正在初始化一个对象 (数组的成员或不是一个引用)而不是一个引用,并调用复制构造函数,那么最好构造被复制的对象。您只能保证它是否在同一个翻译单元中定义。

于 2013-09-02T15:10:23.537 回答
0

我会说是的你可能会遇到静态初始化命令惨败。

您还没有遇到它的原因是应用程序还没有变得足够复杂,无法创建循环静态初始化。

我认为使用数组没有任何区别。

无论如何,这不值得冒险。我将从以下模式开始并根据需要对其进行改进,即创建一个静态类或最适合您目的的任何东西。

#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!";
}
于 2013-09-02T15:30:34.413 回答
0

也许这个问题在提问的过程中被简化了,但是这里有很多关于基本上更简单的东西的争论。

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);
于 2013-09-02T15:33:47.250 回答