正如@ecatmur 所写,初始化是逐行执行的。所以:
- std::map foo::sqlenumToInt = initEnumToInt();
- std::map foo::defaultIt = std::map::iterator();
为了解释它,我写了一个简单的例子:
// foo.h
#pragma once
#include <iostream>
struct bar
{
int value_;
bar(int value)
{
std::cout << "bar()\n";
set(value, true);
}
void set(int value, bool fromConstructor = false)
{
std::cout << ((fromConstructor) ? "Set from ctor" : "Set from non-ctor")
<< ", old value is: " << value_ << "\n";
value_ = value;
}
};
struct foo
{
static bar bar_;
static bool init()
{
std::cout << "init begin\n";
bar_.set(1);
std::cout << "init end\n";
return true;
}
};
// main.cpp
#include "foo.h"
bool b = foo::init();
bar foo::bar_ = bar(2);
int main()
{
std::cout << foo::bar_.value_ << "\n";
return 0;
}
输出是:
init begin
Set from non-ctor, old value is: 0
init end
bar()
Set from ctor, old value is: 1
2
因此,分配了静态变量的内存,但稍后执行初始化,类似于“放置新”机制。您可以在输出中看到,在 init 之后调用了 bar 的 c'tor,但旧值为 1(将由 init 方法设置)并由于静态初始化而被覆盖为 2。
因此,您可以通过更改顺序静态初始化来轻松解决该问题。但是您还有@Kerrek SB 描述的另一个问题:
(此外,即使您在函数中获得的迭代器也将毫无意义,因为一旦本地地图对象被破坏,它就会变得无效。)
纠正您的情况的变体之一:
class foo
{
typedef std::map<std::string, int> Map;
static bool initEnumToInt();
static Map sqlenumToInt;
static Map::iterator defaultIt;
static bool inited;
};
foo::Map foo::sqlenumToInt;
foo::Map::iterator defaultIt = foo::Map::iterator();
bool foo::sqlenumToInt = initEnumToInt();
bool foo::initEnumToInt();
{
defaultIt = sqlenumToInt.insert(std::make_pair("a", 0)).first;
sqlenumToInt["b"] = 2;
sqlenumToInt["c"] = 3;
sqlenumToInt["d"] = 4;
return true;
}