将结构存储在地图中; 检查地图中是否存在结构

Acu*_*ute 1 c++ search constructor struct map

问题#1)下面的结构不希望被复制并给出编译错误 - 为什么以及如何处理它?

#include <iostream>
#include <string>
#include <map>

using namespace std;

struct person
{
    person(string n)
        :name(n)
    {}

    string name;
};

int main()
{
    map<string, person> my_map;

    my_map["one"] = person("Tom");

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

Q#2)我们可以通过省略结构构造函数"person(const string&n)"并逐个分配结构值来避免上述问题:

#include <iostream>
#include <string>
#include <map>

using namespace std;

struct person
{
    string name;
};

int main()
{
    map<string, person> my_map;

    person p;
    p.name = "Tom";
    my_map["one"] = p;

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

所以,让我说我这样做,并且在地图中存储了很多人之后,我想检查一个特定的人是否存在于地图中.据我所知,正确的做法是:

if(my_map.find("one") == my_map.end()) { //it doesn't exist in my_map }  
else {//it exists}
Run Code Online (Sandbox Code Playgroud)

但据我所知,这将逐一遍历整个地图,不是吗?如果是,那么可以这样做:

using namespace std;

struct person
{
    string name;
    string identifier; // <--
};

int main()
{
    map<string, person> my_map;

    person p;
    p.name = "Tom";
    p.identifier = "something"; // <--
    my_map["one"] = p;

    if(my_map["unknown"].identifier == "something") // <--
        cout << "Found" << endl;
    else 
        cout << "Not found" << endl;

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

通过这样做,我们避免迭代,并且内存中的垃圾与我们的标识符匹配的可能性是......小我猜,特别是如果我们使用一些哈希.那样可以(安全)这样做吗?

Man*_*rse 8

1)由于以下表达式,第一个示例中的代码无法编译:

my_map["one"]
Run Code Online (Sandbox Code Playgroud)

my_map["one"]构造一个std::stringfrom "one",并将其传递给std :: map :: operator [].map::operator[]确保将值映射到提供的键(通过将键与默认构造的值相关联,如果它尚未与值关联)并返回对该值的引用.

这不会编译,因为person没有默认构造函数("默认构造函数"是不带参数的构造函数).

有几种方法可以解决这个问题.

一种方法是你采取的方式 - 删除构造函数.它的工作原理是,如果您不提供任何构造函数,则将隐式定义默认构造函数.

另一种方法是显式定义默认构造函数person:

struct person
{
    person():name(){} //or person()=default; if your compiler supports this
    person(string n)
        :name(n)
    {}
    string name;
};
Run Code Online (Sandbox Code Playgroud)

另一种方法是根本不使用operator[],而是使用map :: insert,如下所示:

auto pair(my_map.insert(std::make_pair(std::string("one"),person("Tom"))));
if (!pair.second) {
    *pair.first = person("Tom");
}
Run Code Online (Sandbox Code Playgroud)

2)在地图中找到元素的正确方法是(如你所说)使用:

if(my_map.find("one") == my_map.end()) {/*it doesn't exist in my_map*/}
else {/*it exists*/}
Run Code Online (Sandbox Code Playgroud)

这并没有在地图上检查每一个元素-事实上,它可能只检查O(log(map.size()))元素.

你的恐惧是完全没有根据的,这是在地图中找到一个元素正确方法,但是你继续的方式暗示了对什么operator[]做了严重的误解.

你问" my_map["unknown"].identifier == "something"如果"unknown"地图中不存在,那么返回的概率是多少?".

对此的答案是,没有任何机会返回true,因为如果地图中没有关键字的值std::string("unknown"),那么operator[]std::string("unknown")与默认构造相关联person,因此identifier将是一个空字符串.