C++ std::map at函数始终引发异常

C++ std::map at函数始终引发异常,c++,c++11,C++,C++11,我有一个基本功能,检查单词是否是键。问题是我的try-catch块总是捕获范围外的异常,即使密钥存在。这个问题只发生在我的isExclusion函数中。如果使用静态字符串在isExclusion函数外部进行检查,则at不会引发异常 还有,是否有更好或更有效的方法来检查密钥是否存在?我宁愿不必遍历键列表 #ifndef TITLES_H_ #define TITLES_H_ #include <algorithm> #include <string>

我有一个基本功能,检查单词是否是键。问题是我的try-catch块总是捕获范围外的异常,即使密钥存在。这个问题只发生在我的isExclusion函数中。如果使用静态字符串在isExclusion函数外部进行检查,则at不会引发异常

还有,是否有更好或更有效的方法来检查密钥是否存在?我宁愿不必遍历键列表

#ifndef TITLES_H_
    #define TITLES_H_

    #include <algorithm>
    #include <string>
    #include <vector>
    #include <map>

    static std::map<std::string, int> exclusions;
    static std::vector<std::string> titles;

    bool isExclusion(std::string word);

#endif
#如果没有标题#_
#定义标题_
#包括
#包括
#包括
#包括
静态std::映射排除;
静态std::向量标题;
布尔isExclusion(标准::字符串字);
#恩迪夫

#包括“titles.h”
#包括
布尔isExclusion(标准::字符串字)
{
尝试
{
除外条款。at(word);
}
捕捉(标准:超出范围e)
{
返回false;
}
返回true;
}

#包括
#包括“titles.h”
int main()
{
除外条款[“is”]=1;
除外条款[“该”]=1;
除外条款[“of”]=1;
除外条款[“和”]=1;
除外条款[“a”]=1;
除外条款[“但”]=1;
除外条款[“作为”]=1;
头衔。推回(“人类的堕落”);
头衔。推回(“人类的提升”);
标题:推回(“老人与海”);
标题:推回(“年轻艺术家的肖像”);
头衔。推回(“男人是男人,但泡泡糖是狗”);
排序(titles.begin(),titles.end());
尝试
{
除外责任。在(“该”);
}
捕捉(标准:超出范围e)
{

std::cout您的问题在于这一行:

static std::map<std::string, int> exclusions;
…然后将此行添加到
titles.cpp
文件中:

std::map<std::string, int> exclusions;
std::地图排除;
这将导致全局变量对所有转换单元可见,并且只有一个实际映射

通常,在头文件中使用
static
关键字(在
struct
class
中声明类变量除外)是个坏主意。有一些例外,但它们是库编写者通常担心的深奥场景

static std::map<std::string, int> exclusions;
因此,在与函数不同的映射上操作

bool isExclusion(std::string word)
{
    try
    {
        exclusions.at(word);    
    }
    catch (std::out_of_range e)
    {
        return false;
    }

    return true;
}
在另一个单元中。第二个单元中的排除项实际上总是空的

您需要删除
static
关键字并将定义移动到其中一个单位(best
main
)。要在另一个单位中使用变量,您必须将其声明为
extern

extern std::map<std::string, int> exclusions;
extern标准::地图排除;
不过,最好不要使用全局变量,而是将map和word vector的引用传递给函数。同时,在传递过程中也要将它们设置为const引用(函数不会修改它们)

bool isExclusion(const std::map&exclusions,const std::string&word)
回答问题: 是否有更好或更有效的方法来检查密钥是否存在

这样做:

if (exclusions.find(word) != exclusions.end())
{
    // no, it does not exist
}
else
{
    // yes, you found it, use 
    // exclusions.at(word)
    // safely
}

事实上,如果我没弄错的话,如果你只使用“排除项。at(word)”当元素不存在时,它会为该键创建一个空元素。

我忘记添加我的标志是-lm-lcrypt-O2-std=c++11-pipe-DONLINE\u判断同一文件的最后两个块部分吗?不,它们在不同的文件中。我知道你的问题所在。另外,我想你希望
排除
成为
,而不是
映射de>,您的
isExclusion()
函数可以更改为一行
返回exclusions.find(word)!=exclusions.end();
我同意@Praetorian,只需做一个小小的修改:如果
exclusions
将变得非常大(停止列表通常会有750-1000字左右)一个
std::unordered_map
可能是一个更好的选择(因为你真的不关心顺序,只关心是否有顺序)。当你这样做时,你最好通过
const
-引用传递
排除项和
单词
exclusions["is"] = 1;
exclusions["the"] = 1;
exclusions["of"] = 1;
exclusions["and"] = 1;
exclusions["a"] = 1;
exclusions["but"] = 1;
exclusions["as"] = 1;
bool isExclusion(std::string word)
{
    try
    {
        exclusions.at(word);    
    }
    catch (std::out_of_range e)
    {
        return false;
    }

    return true;
}
extern std::map<std::string, int> exclusions;
bool isExclusion(const std::map<std::string, int>& exclusions, const std::string& word)
if (exclusions.find(word) != exclusions.end())
{
    // no, it does not exist
}
else
{
    // yes, you found it, use 
    // exclusions.at(word)
    // safely
}