I'm trying to implement a lightweight map by simply using an array of elements whose members are a key and a value. The map contents are known at compile-time so I think of using a fixed-size array as follows:
#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();
}
Now to my question: The code snippet works as intended but I somehow have the feeling that I'm relying on the initialization order to have the ITEM1 to ITEM4 having their content initialized before using them in the ItemMapUser::map. I searched through the many questions referring to this topic (especially those with the static-order-fiasco tag) but couldn't find any one related to the use of arrays.
- May I encounter the initialization order fiasco?
- If no, what prevents it from happening here?
- Does it matter that I'm using an array? How would it look like if I tried to initialize a simple variable using
const Item anotherItem = ITEM1;
for example?
Do you use
ItemMapUser::map
in code which can be called from the constructor of a static object? There's no problem initializing the references with unconstructed objects, but there will be if you use them before the object is constructed.Re your questions:
Not unless you actually use the objects the references designate in the constructor of a static object.
Basically, the fact that these are references, and you can safely initialize a referene with an unconstructed object. (There are certain restrictions when inheritance is involved, but they don't seem to be relevant here.)
It has nothing to do with whether you're initializing an object or an array. If you're initialization an object (member of an array or not) rather than a reference, and calling the copy constructor, the object being copied had better be constructed. Which you can only guarantee if it is defined in the same translation unit.