简体   繁体   English

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

[英]std::map at function always throwing exception

I have a basic function that checks if the word is a key.我有一个基本的函数来检查这个词是否是一个键。 The problem is my try catch block is always catching a out_of_range exception, even when the key exists.问题是我的 try catch 块总是捕获 out_of_range 异常,即使键存在也是如此。 This problem only occurrs in my isExclusion function.这个问题只发生在我的 isExclusion 函数中。 If I check outside the isExclusion function with a static string then at will not throw the exception.如果我使用静态字符串在 isExclusion 函数之外进行检查,则 at 不会抛出异常。

Also, is there a better or more effecient way to check if the key exists?另外,是否有更好或更有效的方法来检查密钥是否存在? I would rather not have to iterate through the list of keys.我宁愿不必遍历键列表。

#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 found\n";
    }
    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 is defined static . exclusions被定义为static static globals are limited in scope to their respective compilation unit. static全局变量的范围仅限于它们各自的编译单元。 This way it is possible to reuse names in several compilation units.这样就可以在多个编译单元中重用名称。

You include this line per #include "titles.h" in both compilation units.您可以在两个编译单元中按照#include "titles.h"包含这一行。 Thereby you actually create two maps with the same name, each one limited to its compilation unit.因此,您实际上创建了两个具有相同名称的映射,每个映射都仅限于其编译单元。

These lines in main这些线路在main

exclusions["is"] = 1;
exclusions["the"] = 1;
exclusions["of"] = 1;
exclusions["and"] = 1;
exclusions["a"] = 1;
exclusions["but"] = 1;
exclusions["as"] = 1;

therefore operate on a different map than the function因此在与函数不同的映射上操作

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

    return true;
}

in the other unit.在另一个单位。 exclusions in the second unit actually is always empty.第二个单元中的exclusions实际上总是空的。

You need to remove the static keyword and move the definition to one of the units (best main ).您需要删除static关键字并将定义移动到单元之一(最好的main )。 To also use the variable in the other unit you have to declare it there as extern :要在另一个单元中使用该变量,您必须在那里将其声明为extern

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

However it would be much better to not use global variables at all and pass references of the map and word vector to the function instead.然而,最好根本不使用全局变量,而是将映射和词向量的引用传递给函数。 Also make them const references while you are at it.在你使用它的时候也让它们成为 const 引用。 (The function does not modify them.) (该函数不会修改它们。)

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

Your problem is with this line:您的问题出在这一行:

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

By defining this variable to be static , you are creating two separate map s in two separate translation units.通过将此变量定义为static ,您将在两个单独的翻译单元中创建两个单独的map main() is using one map and titles.cpp is using the other. main()正在使用一张maptitles.cpp正在使用另一张map Instead, declare the variable like this:相反,像这样声明变量:

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

. . . . . . and then add this line into your titles.cpp file:然后将此行添加到titles.cpp文件中:

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

This will cause the global variable to be visible to all translation units, and there will only be one actual map.这将导致全局变量对所有翻译单元可见,并且只有一张实际地图。

Generally it is a bad idea to use the static keyword in a header file (except within a struct or class to declare class variables).通常在头文件中使用static关键字是一个坏主意(除了在structclass中声明类变量)。 There are a few exceptions, but they are the esoteric scenarios that library writers usually worry about.有一些例外,但它们是图书馆作者通常担心的深奥场景。

to answer the question: is there a better or more effecient way to check if the key exists?回答这个问题:有没有更好或更有效的方法来检查密钥是否存在?

do this:做这个:

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

actually, if I am not mistaken, if you just use "exclusions.at(word)" when the element does not exists, it creates an empty element for this key.实际上,如果我没记错的话,如果您在元素不存在时仅使用“exclusions.at(word)”,它会为此键创建一个空元素。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM