C++ C++;映射将向量下标抛出范围之外
我正在尝试创建一个类,该类将其实例存储在映射中,如下所示:C++ C++;映射将向量下标抛出范围之外,c++,stl,unordered-map,C++,Stl,Unordered Map,我正在尝试创建一个类,该类将其实例存储在映射中,如下所示: class Apple { public: static Apple* getApple(const std::string &name) { auto it = allApples.find(name); if (it == allApples.end()) // if this apple doesnt exist, make a new one
class Apple {
public:
static Apple* getApple(const std::string &name) {
auto it = allApples.find(name);
if (it == allApples.end()) // if this apple doesnt exist, make a new one
return new Apple(name);
else // if the apple exists, return its pointer
return it->second;
}
private:
static std::unordered_map<std::string, Apple*> allApples =
std::unordered_map<std::string, Apple*>();
Apple(const std::string &name) {
// create an apple
allApples.insert({ name, this });
}
}
当我运行该程序时,它在getApple()方法的第一行崩溃,并出现向量下标超出范围的错误。我试着四处看看,但我真的找不到任何解决方案来处理地图和这个超出范围的错误。根据我所做的一些研究,我的猜测是关于静态顺序初始化的,但我真的不太确定。首先,getApple方法应该是静态的,并且应该在类之外初始化类成员(静态成员)。试试这个-
class Apple {
public:
static Apple* getApple(const std::string &name) {
auto it = allApples.find(name);
if (it == allApples.end()) // if this apple doesnt exist, make a new one
return new Apple(name);
else // if the apple exists, return its pointer
return it->second;
}
private:
static std::unordered_map<std::string, Apple*> allApples;
Apple(const std::string &name) {
// create an apple
allApples.insert({ name, this });
}
};
std::unordered_map<std::string, Apple*> Apple::allApples = std::unordered_map<std::string, Apple*>();
class Orange {
static Apple *myOrangeApple;
};
Apple * Orange::myOrangeApple=Apple::getApple("orange");
苹果类{
公众:
静态Apple*getApple(const std::string和name){
auto it=allApples.find(名称);
if(it==allApples.end())//如果这个苹果不存在,就做一个新的
返回新苹果(名称);
else//如果苹果存在,则返回其指针
返回->秒;
}
私人:
静态std::无序映射所有应用程序;
苹果(const std::string和name){
//创造一个苹果
插入({name,this});
}
};
std::无序映射Apple::allApples=std::无序映射();
橙色类{
静态苹果*myorange苹果;
};
苹果*Orange::myOrangeApple=Apple::getApple(“橙色”);
在初始化之前,您正在访问所有应用程序。在您输入
main
之前,无法保证allApples
已构建,因此访问它是绝对不允许的
让类自己添加到容器中是个坏主意,但在全局对象中这样做真的很糟糕。不要这样做。使用函数范围静态对象
...
private:
std::unordered_map<std::string, Apple*>& allApples() {
static std::unordered_map<std::string, Apple*> apples;
return apples;
}
。。。
私人:
标准::无序地图和所有地图(){
静态标准::无序的_图苹果;
还苹果;
}
这是对抗静态初始化命令失败的标准方法之一。它之所以有效,是因为块作用域静态对象保证在第一次执行块时初始化
如果以这种方式管理的对象之间存在相互依赖关系,则此方法将不起作用 你指的第一行是
autoit=allApples.find(name)代码>?我看不到任何与std::vector
或下标运算符相关的内容。@songyuanyao,是的,该行是抛出调试断言/异常(在发布版本中)的行。我也看不到任何与向量相关的东西,这就是为什么我如此困惑的原因。你能给我们足够的代码,让我们可以编译它并复制这个问题吗?@DavidSchwartz,这就是它的全部。。。除了一个函数和构造函数之外,我没有访问allApples
映射,因此编写main
函数并确认它复制了问题应该没有问题。请这样做。我有这样的代码,我可能应该在这里更改它,我只是不认为它与问题有那么大的关系。@ThomasPaine没有足够的代码来复制问题,任何人都无法判断什么是相关的或不相关的。但是当我在断点之前打印出allApples
的大小时,它给我零,这意味着allApples
已初始化,对吗?如果allApples
没有初始化,那不是未定义的行为吗?@thomaspine这是代码中的另一个bug。在确保所有应用程序都已初始化为UB之前,不得调用size
。你刚好得到零,这误导了你。这就是为什么你不应该这么做!这就是为什么您应该在构造函数和析构函数中尽可能少地执行操作——很难控制它们执行的上下文。让这么多的代码都从全局静态的构造函数调用是愚蠢的。您如何维护这段代码,而不在代码上到处贴上“请勿在MAIN之前执行任何不合法的操作”的大警告,并通过所有调用的函数传播这些警告?疯了,在这种情况下我该怎么办?构建苹果非常昂贵(这是一个文件导入和处理过程),因此我不想每次需要访问苹果时都构建它们。您可以使用一个工厂类来管理苹果。这是一个很好的建议,但作为一个答案,如果您解释为什么这样做会更好,那会更好。
...
private:
std::unordered_map<std::string, Apple*>& allApples() {
static std::unordered_map<std::string, Apple*> apples;
return apples;
}