std::map at 函数总是抛出异常

std::map at function always throwing exception

本文关键字:抛出异常 at map std 函数      更新时间:2023-10-16

我有一个基本函数来检查单词是否是键。问题是我的 try catch 块总是捕获out_of_range异常,即使密钥存在也是如此。此问题仅发生在我的 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

#include "titles.h"
#include <iostream>
bool isExclusion(std::string word)
{
try
{
exclusions.at(word);    
}
catch (std::out_of_range e)
{
return false;
}
return true;
}

#include <iostream>
#include "titles.h"
int main()
{
exclusions["is"] = 1;
exclusions["the"] = 1;
exclusions["of"] = 1;
exclusions["and"] = 1;
exclusions["a"] = 1;
exclusions["but"] = 1;
exclusions["as"] = 1;
titles.push_back("Descent of Man");
titles.push_back("The Ascent of Man");
titles.push_back("The Old Man and The Sea");
titles.push_back("A Portrait of the Artist As a Young Man");
titles.push_back("A Man is a Man but Bubblesort IS A DOG");
std::sort(titles.begin(), titles.end());
try
{
exclusions.at("the");
}
catch(std::out_of_range e)
{
std::cout << "Not foundn";
}
std::cout << "Exclusion?: " << isExclusion("hello") << std::endl;
std::cout << "Exclusion?: " << isExclusion("the") << std::endl;
for(auto i = titles.begin(); i != titles.end(); i++)
{
std::cout << *i << "n";
}
return 0;
}
static std::map<std::string, int> exclusions;

exclusions定义static.static全局变量的范围仅限于其各自的编译单元。这样,就可以在多个编译单元中重用名称。

您可以在两个编译单元中包括每个#include "titles.h"的此行。因此,您实际上创建了两个具有相同名称的映射,每个映射都仅限于其编译单元。

这些行在main

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;
}

在另一个单元。 第二个单元中的exclusions实际上总是空的。

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

extern std::map<std::string, int> exclusions;

但是,最好根本不使用全局变量,而是将映射和单词向量的引用传递给函数。当您使用它时,还可以使它们成为常量引用。(该函数不会修改它们。

bool isExclusion(const std::map<std::string, int>& exclusions, const std::string& word)

你的问题出在以下行上:

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

通过定义这个变量static,您将在两个单独的翻译单元中创建两个单独的mapmain()正在使用一种maptitles.cpp正在使用另一种。 相反,像这样声明变量:

extern std::map<std::string, int> exclusions;

。,然后将此行添加到titles.cpp文件中:

std::map<std::string, int> exclusions;

这将导致全局变量对所有翻译单元可见,并且只有一个实际映射。

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

来回答这个问题: 是否有更好或更有效的方法来检查密钥是否存在?

这样做:

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

实际上,如果我没记错的话,如果您在元素不存在时只使用"exclusions.at(word)",它会为此键创建一个空元素。