C++ unordered_map 移动初学者错误

C++ unordered_map move beginner error

很抱歉这里的菜鸟问题,但我什至不知道要在 google 上搜索什么。我尝试了一些关于移动语义的文档,但我仍然无法解决我的问题。

所以如果有人能给我一些线索,我将非常感激。

关于代码:

graph.hpp:

#ifndef  GRAPH_HPP
#define  GRAPH_HPP

#include  <cstdlib>
#include  <unordered_map>
#include  <vector>
#include  <string>

template<typename T, typename U>
class  Link;
template<typename T, typename U>
class  Node;

namespace  graph
{
  template<typename T, typename U>
  class  Link
    {
      public:
    Link() = default;
    Link(U&& data, T& node) : _data(data), _endNode(node) {}
    ~Link() = default;

      private:
    U            _data;
    Node<T, U>&  _endNode;
    };

  template<typename T, typename U>
  class  Node
    {
      public:
    Node() = default;
    Node(T&& data) : _data(data) {};
    ~Node() = default;

    private:
      T                        _data;
      std::vector<Link<T, U>>  _links;
    };

  template<typename K, typename T, typename U>
  class  Graph
    {
      public:
        Graph() = default;
        ~Graph() = default;

      private:
        size_t                             _nbNode;
        std::unordered_map<K, Node<T, U>>  _nodes;

      public:
        #include  "graph.tpp"
    };
}
#endif

graph.tpp:

void  add_Link(const K& key1,
           const K& key2,
           U&& linkInfo)
{
  if (!_nodes.count(key1)
      || !_nodes.count(key2))
    throw "Key doesn't exist!";

  Link<T, U>  newLink(linkInfo, _nodes[key2]);
  _nodes[key1].links.push_back(newLink);
}

void  add_Node(K& key, T&& elem)
{
  Node<T, U>  newNode(std::move(elem));
  _nodes[key] = std::move(newNode);
}

main.cpp:

#include  "graph.hpp"
#include  <string>

int main()
{
  std::string  name("name");
  graph::Graph<std::string, std::string, std::string>  graph;

  graph.add_Node(name, "lol");
  return 0;
}

我只是想在 unordered_map 中添加一个新元素。但它只是说我 :

    clang++ -Wall -Wextra -std=c++14 -O2 -march=native -s -fomit-frame-pointer -c src/test.cpp -o obj/test.o -I ./src/include -I ./src/template/
clang: warning: argument unused during compilation: '-s'
In file included from src/test.cpp:1:
In file included from ./src/include/graph.hpp:15:
In file included from /usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/unordered_map:41:
In file included from /usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/tuple:39:
In file included from /usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/array:38:
In file included from /usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/stdexcept:39:
In file included from /usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/string:40:
In file included from /usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/bits/char_traits.h:39:
/usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/bits/stl_algobase.h:336:18: error: object of type 'graph::Link<std::basic_string<char>, std::basic_string<char> >' cannot be assigned because its copy
      assignment operator is implicitly deleted
              *__result = *__first;
                        ^
/usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/bits/stl_algobase.h:396:36: note: in instantiation of function template specialization 'std::__copy_move<false, false,
      std::random_access_iterator_tag>::__copy_m<const graph::Link<std::basic_string<char>, std::basic_string<char> > *, graph::Link<std::basic_string<char>, std::basic_string<char> > *>' requested here
                              _Category>::__copy_m(__first, __last, __result);
                                          ^
/usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/bits/stl_algobase.h:432:23: note: in instantiation of function template specialization 'std::__copy_move_a<false, const graph::Link<std::basic_string<char>,
      std::basic_string<char> > *, graph::Link<std::basic_string<char>, std::basic_string<char> > *>' requested here
      return _OI(std::__copy_move_a<_IsMove>(std::__niter_base(__first),
                      ^
/usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/bits/stl_algobase.h:464:20: note: in instantiation of function template specialization 'std::__copy_move_a2<false, __gnu_cxx::__normal_iterator<const
      graph::Link<std::basic_string<char>, std::basic_string<char> > *, std::vector<graph::Link<std::basic_string<char>, std::basic_string<char> >, std::allocator<graph::Link<std::basic_string<char>, std::basic_string<char> > > > >,
      __gnu_cxx::__normal_iterator<graph::Link<std::basic_string<char>, std::basic_string<char> > *, std::vector<graph::Link<std::basic_string<char>, std::basic_string<char> >, std::allocator<graph::Link<std::basic_string<char>,
      std::basic_string<char> > > > > >' requested here
      return (std::__copy_move_a2<__is_move_iterator<_II>::__value>
                   ^
/usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/bits/vector.tcc:206:27: note: in instantiation of function template specialization 'std::copy<__gnu_cxx::__normal_iterator<const
      graph::Link<std::basic_string<char>, std::basic_string<char> > *, std::vector<graph::Link<std::basic_string<char>, std::basic_string<char> >, std::allocator<graph::Link<std::basic_string<char>, std::basic_string<char> > > > >,
      __gnu_cxx::__normal_iterator<graph::Link<std::basic_string<char>, std::basic_string<char> > *, std::vector<graph::Link<std::basic_string<char>, std::basic_string<char> >, std::allocator<graph::Link<std::basic_string<char>,
      std::basic_string<char> > > > > >' requested here
              std::_Destroy(std::copy(__x.begin(), __x.end(), begin()),
                                 ^
./src/include/graph.hpp:40:10: note: in instantiation of member function 'std::vector<graph::Link<std::basic_string<char>, std::basic_string<char> >, std::allocator<graph::Link<std::basic_string<char>, std::basic_string<char> > >
      >::operator=' requested here
  class  Node
         ^
src/test.cpp:9:9: note: in instantiation of member function 'graph::Graph<std::basic_string<char>, std::basic_string<char>, std::basic_string<char> >::add_Node' requested here
  graph.add_Node(name, "lol");
        ^
./src/include/graph.hpp:36:15: note: copy assignment operator of 'Link<std::basic_string<char>, std::basic_string<char> >' is implicitly deleted because field '_endNode' is of reference type
      'Node<std::basic_string<char>, std::basic_string<char> > &'
        Node<T, U>&  _endNode;
                     ^
In file included from src/test.cpp:1:
In file included from ./src/include/graph.hpp:15:
In file included from /usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/unordered_map:41:
In file included from /usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/tuple:39:
In file included from /usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/array:38:
In file included from /usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/stdexcept:39:
In file included from /usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/string:40:
In file included from /usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/bits/char_traits.h:39:
/usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/bits/stl_algobase.h:336:18: error: object of type 'graph::Link<std::basic_string<char>, std::basic_string<char> >' cannot be assigned because its copy
      assignment operator is implicitly deleted
              *__result = *__first;
                        ^
/usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/bits/stl_algobase.h:396:36: note: in instantiation of function template specialization 'std::__copy_move<false, false,
      std::random_access_iterator_tag>::__copy_m<graph::Link<std::basic_string<char>, std::basic_string<char> > *, graph::Link<std::basic_string<char>, std::basic_string<char> > *>' requested here
                              _Category>::__copy_m(__first, __last, __result);
                                          ^
/usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/bits/stl_algobase.h:432:23: note: in instantiation of function template specialization 'std::__copy_move_a<false, graph::Link<std::basic_string<char>,
      std::basic_string<char> > *, graph::Link<std::basic_string<char>, std::basic_string<char> > *>' requested here
      return _OI(std::__copy_move_a<_IsMove>(std::__niter_base(__first),
                      ^
/usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/bits/stl_algobase.h:464:20: note: in instantiation of function template specialization 'std::__copy_move_a2<false, graph::Link<std::basic_string<char>,
      std::basic_string<char> > *, graph::Link<std::basic_string<char>, std::basic_string<char> > *>' requested here
      return (std::__copy_move_a2<__is_move_iterator<_II>::__value>
                   ^
/usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/bits/vector.tcc:211:13: note: in instantiation of function template specialization 'std::copy<graph::Link<std::basic_string<char>, std::basic_string<char> >
      *, graph::Link<std::basic_string<char>, std::basic_string<char> > *>' requested here
              std::copy(__x._M_impl._M_start, __x._M_impl._M_start + size(),
                   ^
./src/include/graph.hpp:40:10: note: in instantiation of member function 'std::vector<graph::Link<std::basic_string<char>, std::basic_string<char> >, std::allocator<graph::Link<std::basic_string<char>, std::basic_string<char> > >
      >::operator=' requested here
  class  Node
         ^
src/test.cpp:9:9: note: in instantiation of member function 'graph::Graph<std::basic_string<char>, std::basic_string<char>, std::basic_string<char> >::add_Node' requested here
  graph.add_Node(name, "lol");
        ^
./src/include/graph.hpp:36:15: note: copy assignment operator of 'Link<std::basic_string<char>, std::basic_string<char> >' is implicitly deleted because field '_endNode' is of reference type
      'Node<std::basic_string<char>, std::basic_string<char> > &'
        Node<T, U>&  _endNode;
                     ^
2 errors generated.
Makefile:43: recipe for target 'obj/test.o' failed
make: *** [obj/test.o] Error 1

抱歉给您带来麻烦,祝您愉快。

好的。问题出在这一行:

_nodes[key] = std::move(newNode);

您正在尝试移动分配 Node<T, U>。但是,Node 不会有一个移动赋值运算符隐式声明为默认,因为有一个用户声明的析构函数:

~Node() = default;

因此,该行实际上调用了 Node<T, U>copy 赋值运算符,它执行成员复制。 Node<T, U> 的成员之一是 std::vector<Link<T, U>> 类型,其中 Link<T, U> 有一个成员变量,它是一个引用。引用不可复制赋值,因此复制赋值运算符被隐式删除。因此,没有找到复制赋值运算符,因此该行格式错误。

虽然引用也不是可移动赋值的,但 vector<Link<T,U>> 是可移动赋值的,因此最简单的解决方案是删除将析构函数声明为默认的行:

//~Node() = default;

这样,编译器将隐式声明默认移动 constructor/assignment,此代码将执行您期望的操作。并编译。

旁注,这是一个非常糟糕的主意:

public:
    #include  "graph.tpp"
};