如何在C++中的unordered_map中插入键/值对?

问题描述 投票:0回答:1

我想构造一个图,其

Vertex
定义如下:

struct Vertex {
    string key;              // key of the vertex.
    vector<string> adj;      // keys of adjacent vertices.
    vector<double> weights;  // weights of edges to adjacent vertices.

    Vertex(string x) : key(x) {}
    Vertex(const Vertex &other) {
        cout << "Copy Constructor\n";
        this->key = other.key;
        this->adj = other.adj;
        this->weights = other.weights;
    }
    Vertex &operator=(const Vertex &other) {
        cout << "Copy Assignment Operator\n";
        if (this != &other) {
            this->key = other.key;
            this->adj = other.adj;
            this->weights = other.weights;
        }
        return *this;
    }
};

首先我定义一个

unordered_map
,它有一对
<string, Vertex>
string a = "a";

我可以构建如下图表:

graph.insert(make_pair(a, Vertex(a)));

但是以下

graph[a] = Vertex(a);

不起作用。它输出错误:

In file included from /usr/include/c++/9/bits/hashtable_policy.h:34,
                 from /usr/include/c++/9/bits/hashtable.h:35,
                 from /usr/include/c++/9/unordered_map:46,
                 from construct_graph.cpp:3:
/usr/include/c++/9/tuple: In instantiation of ‘std::pair<_T1, _T2>::pair(std::tuple<_Args1 ...>&, std::tuple<_Args2 ...>&, std::_Index_tuple<_Indexes1 ...>, std::_Index_tuple<_Indexes2 ...>) [with _Args1 = {const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&}; long unsigned int ..._Indexes1 = {0}; _Args2 = {}; long unsigned int ..._Indexes2 = {}; _T1 = const std::__cxx11::basic_string<char>; _T2 = Vertex]’:
/usr/include/c++/9/tuple:1663:63:   required from ‘std::pair<_T1, _T2>::pair(std::piecewise_construct_t, std::tuple<_Args1 ...>, std::tuple<_Args2 ...>) [with _Args1 = {const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&}; _Args2 = {}; _T1 = const std::__cxx11::basic_string<char>; _T2 = Vertex]’
/usr/include/c++/9/ext/new_allocator.h:146:4:   required from ‘void __gnu_cxx::new_allocator<_Tp>::construct(_Up*, _Args&& ...) [with _Up = std::pair<const std::__cxx11::basic_string<char>, Vertex>; _Args = {const std::piecewise_construct_t&, std::tuple<const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&>, std::tuple<>}; _Tp = std::__detail::_Hash_node<std::pair<const std::__cxx11::basic_string<char>, Vertex>, true>]’
/usr/include/c++/9/bits/alloc_traits.h:483:4:   required from ‘static void std::allocator_traits<std::allocator<_CharT> >::construct(std::allocator_traits<std::allocator<_CharT> >::allocator_type&, _Up*, _Args&& ...) [with _Up = std::pair<const std::__cxx11::basic_string<char>, Vertex>; _Args = {const std::piecewise_construct_t&, std::tuple<const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&>, std::tuple<>}; _Tp = std::__detail::_Hash_node<std::pair<const std::__cxx11::basic_string<char>, Vertex>, true>; std::allocator_traits<std::allocator<_CharT> >::allocator_type = std::allocator<std::__detail::_Hash_node<std::pair<const std::__cxx11::basic_string<char>, Vertex>, true> >]’
/usr/include/c++/9/bits/hashtable_policy.h:2086:36:   required from ‘std::__detail::_Hashtable_alloc<_NodeAlloc>::__node_type* std::__detail::_Hashtable_alloc<_NodeAlloc>::_M_allocate_node(_Args&& ...) [with _Args = {const std::piecewise_construct_t&, std::tuple<const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&>, std::tuple<>}; _NodeAlloc = std::allocator<std::__detail::_Hash_node<std::pair<const std::__cxx11::basic_string<char>, Vertex>, true> >; std::__detail::_Hashtable_alloc<_NodeAlloc>::__node_type = std::__detail::_Hash_node<std::pair<const std::__cxx11::basic_string<char>, Vertex>, true>]’
/usr/include/c++/9/bits/hashtable_policy.h:701:8:   required from ‘std::__detail::_Map_base<_Key, _Pair, _Alloc, std::__detail::_Select1st, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits, true>::mapped_type& std::__detail::_Map_base<_Key, _Pair, _Alloc, std::__detail::_Select1st, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits, true>::operator[](const key_type&) [with _Key = std::__cxx11::basic_string<char>; _Pair = std::pair<const std::__cxx11::basic_string<char>, Vertex>; _Alloc = std::allocator<std::pair<const std::__cxx11::basic_string<char>, Vertex> >; _Equal = std::equal_to<std::__cxx11::basic_string<char> >; _H1 = std::hash<std::__cxx11::basic_string<char> >; _H2 = std::__detail::_Mod_range_hashing; _Hash = std::__detail::_Default_ranged_hash; _RehashPolicy = std::__detail::_Prime_rehash_policy; _Traits = std::__detail::_Hashtable_traits<true, false, true>; std::__detail::_Map_base<_Key, _Pair, _Alloc, std::__detail::_Select1st, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits, true>::mapped_type = Vertex; std::__detail::_Map_base<_Key, _Pair, _Alloc, std::__detail::_Select1st, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits, true>::key_type = std::__cxx11::basic_string<char>]’
/usr/include/c++/9/bits/unordered_map.h:986:20:   required from ‘std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::mapped_type& std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::operator[](const key_type&) [with _Key = std::__cxx11::basic_string<char>; _Tp = Vertex; _Hash = std::hash<std::__cxx11::basic_string<char> >; _Pred = std::equal_to<std::__cxx11::basic_string<char> >; _Alloc = std::allocator<std::pair<const std::__cxx11::basic_string<char>, Vertex> >; std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::mapped_type = Vertex; std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::key_type = std::__cxx11::basic_string<char>]’
construct_graph.cpp:34:12:   required from here
/usr/include/c++/9/tuple:1674:70: error: no matching function for call to ‘Vertex::Vertex()’
 1674 |         second(std::forward<_Args2>(std::get<_Indexes2>(__tuple2))...)
      |                                                                      ^
construct_graph.cpp:14:5: note: candidate: ‘Vertex::Vertex(const Vertex&)’
   14 |     Vertex(const Vertex &other) {
      |     ^~~~~~
construct_graph.cpp:14:5: note:   candidate expects 1 argument, 0 provided
construct_graph.cpp:13:5: note: candidate: ‘Vertex::Vertex(std::string)’
   13 |     Vertex(string x) : key(x) {}
      |     ^~~~~~
construct_graph.cpp:13:5: note:   candidate expects 1 argument, 0 provided

似乎在

Vertex
中找不到构造
graph
对象的构造函数。但我不明白为什么它找不到构造函数。

完整代码如下:

#include <iostream>
#include <string>
#include <unordered_map>
#include <vector>

using namespace std;

struct Vertex {
    string key;              // key of the vertex.
    vector<string> adj;      // keys of adjacent vertices.
    vector<double> weights;  // weights of edges to adjacent vertices.

    Vertex(string x) : key(x) {}
    Vertex(const Vertex &other) {
        cout << "Copy Constructor\n";
        this->key = other.key;
        this->adj = other.adj;
        this->weights = other.weights;
    }
    Vertex &operator=(const Vertex &other) {
        cout << "Copy Assignment Operator\n";
        if (this != &other) {
            this->key = other.key;
            this->adj = other.adj;
            this->weights = other.weights;
        }
        return *this;
    }
};

void construct_graph() {
    unordered_map<string, Vertex> graph;
    string a = "a";
    // graph[a] = Vertex(a);  // doesn't work.
    graph.insert(make_pair(a, Vertex(a)));
}

// g++ construct_graph.cpp && ./a.out
int main(void) {
    construct_graph();
    return 0;
}
c++ constructor unordered-map
1个回答
0
投票

graph[a]
被调用时,它无法提前知道你要对结果做什么(无论你是要做
= Vertex(a)
还是其他事情),所以该值将首先使用它的默认构造函数。然后
= Vertex(a)
执行分配。

其他插入元素的方式,例如

.insert()
,会立即接收构造函数参数,因此可以直接调用正确的构造函数。

编译器不会为您的类生成默认构造函数,因为您添加了自定义构造函数。有一个默认构造函数是个好主意(尽管在地图上使用

[]
不是),请使用
Vertex() {}
添加它。

也不要手动定义复制构造函数/赋值、移动构造函数/赋值和析构函数,除非您确实需要(在本例中您不需要),因为编译器可能会在生成它们方面做得更好。例如。在这种情况下,通过手动定义复制操作,您会丢失移动操作。

© www.soinside.com 2019 - 2024. All rights reserved.