我正在尝试将int设置为int map,但程序崩溃了,我没有意识到原因。 我已经将问题总结为这个简短的简单代码。
当程序启动时,由于Utilities成员_instance是静态的 - 它通过转到其构造函数来初始化它,该构造函数包含一行:int到int(简单)映射赋值。但随后就崩溃了。
请注意,如果我评论该行,程序不会崩溃, 并且主要包含同一行。 所以我的两个问题是:
1)为什么会崩溃?这种行为背后有一点吗?
2)如何修复它以便我可以在构造函数中初始化地图?
谢谢
#include <map>
class Utilities
{
public:
~Utilities(){};
static Utilities& instance();
private:
Utilities();
Utilities( const Utilities& ){};
static Utilities _instance;
static std::map<int, int> textIntToIntMap;
};
Utilities Utilities::_instance = Utilities();
std::map<int, int> Utilities::textIntToIntMap;
Utilities::Utilities()
{
//The following line crashes, why?
textIntToIntMap[1] = 2;
}
int main()
{
static std::map<int, int> text2;
text2[4] = 2;
int xxx = 3;
}
答案 0 :(得分:1)
问题是您在Utilities
构建之前调用了Utilities::textIntToIntMap
构造函数。
交换以下两行的顺序:
Utilities Utilities::_instance = Utilities();
std::map<int, int> Utilities::textIntToIntMap;
答案 1 :(得分:1)
您有初始化订单问题:
Utilities Utilities::_instance = Utilities();
此行调用Utilities
的默认构造函数,然后尝试填充地图。但是现阶段没有初始化地图。
您应该设计您的代码以抵御此类初始化顺序问题。您可以通过在函数内创建静态实例来缓解其中的一些问题。这使您可以处理初始化的顺序。但是,定义的简单重新排序应该可以解决当前的问题:
std::map<int, int> Utilities::textIntToIntMap;
Utilities Utilities::_instance = Utilities(); // OK, map has been defined
答案 2 :(得分:0)
在初始化_instance之前,您需要在类外部定义map textTntIntMap。因为在构造函数中,您使用的是textIntToIntMap,它是一个静态成员,因此您需要先定义它。所以在课外使用以下几行:
std::map<int, int> Utilities::textIntToIntMap;
Utilities Utilities::_instance = Utilities();
答案 3 :(得分:0)
其他人已经发现在Utilities()
之前构建了Utilities::textToIntMap
。那么,现在的问题是:将来如何避免这些问题?
您可以使用函数返回对静态局部变量的引用,以确保在使用引用之前完成构造。您可以将此类函数放入命名空间。您还应该有一个方便的typedef,希望更短的名称,因此声明迭代器不是C ++ 98的断言。在C ++ 11上,无论如何你应该使用auto
。
请注意,在C ++ 98中使用全局或函数静态非POD数据不是线程安全的。如果您希望安全地从多个线程使用textToMap()
,并且不保证在第二个线程启动之前访问它,textToIntMap
将需要在互斥锁中包装初始化。要大致了解如何执行此操作,请参阅Qt方便的Q_GLOBAL_STATIC
中的inner function。
在这种情况下,使用单例类似乎是毫无意义的Java主义。
// Utilities.h
namespace Utilities {
typedef std::map<int, int> Map;
Map & textToIntMap();
}
// Utilities.cpp
namespace Utilities {
namespace {
struct InitializedMap : Map {
InitializedMap() {
insert(value_type(1, 2));
// or
(*this)[1] = 2;
}
};
}
Map & textToIntMap() {
static InitializedMap map;
return map;
}
}
答案 4 :(得分:0)
试试这个::
#include <map>
#include <iostream>
using namespace std;
class Utilities
{
public:
static Utilities& instance() {
static Utilities instance;
return instance;
}
~Utilities(){};
void PrintMapValues();
void AddKeyValue(int key, int value);
private:
Utilities();
Utilities( const Utilities& ){};
std::map<int, int> int_to_int_map_;
};
Utilities::Utilities()
{
//The following line crashes, why?
int_to_int_map_[-99] = 2;
}
void Utilities::PrintMapValues() {
for(std::map<int, int>::iterator it = int_to_int_map_.begin(); it != int_to_int_map_.end(); ++it){
cout << "Key:" << it->first << " Val:" << it->second << endl;
}
}
void Utilities::AddKeyValue(int key, int value) {
int_to_int_map_[key] = value;
}
int main()
{
Utilities& utils = Utilities::instance();
for (int i=0; i< 10; i++) {
utils.AddKeyValue(i, i+20);
}
utils.PrintMapValues();
return 0;
}