C++ 在定义或声明 class 析构函数时使用已删除的函数

C++ Use of deleted function when defining or declaring class destructor

我正在尝试制作一个真正基本的组件实体系统,到目前为止我已经成功了。我已经可以将任何类型的组件添加到实体中。但是,我正在努力为我的节点列表对象(用于轻松删除组件的双链表)实现任何类型的析构函数。

本质上,在我的系统中,一个单独的对象包含一个 unordered_map(标准实现),它以一个 boost::uuid 作为键并包含一个 T 类型的列表(模板)。这就像一个 unordered_multimap 但更容易递归访问等。(我个人不喜欢迭代器实现,因为我无法在没有实体泄漏到其他实体的情况下让它工作,但那只是我)。

无论如何,class 我试图为列表模板 class 创建析构函数。这是它的完整定义:

#ifndef LIST_H_INCLUDED
#define LIST_H_INCLUDED
#include "node.h"

template<class t>
class List:InstanceCounted<List<t>>
{
private:
    typedef Node<t> NodeT;
    std::unique_ptr<NodeT> head;
    void initHead(const t &data)
    {
        this->head=std::make_unique<NodeT>(data);
        this->head->setNext(nullptr);
        this->head->setPrev(nullptr);
    }
public:
    List()
    {}
    List(const t &data)
    {
        this->initHead(data);
    }
    NodeT* getHead()
    {
        return &*this->head;
    }
    void addNew(const t &data)
    {
        NodeT *last;
        try
        {
            last = &*this->head;
            while(last&&last->getNext())
            {
                last=last->getNext();
            }
            last->setNext(new NodeT(data));
            last->getNext()->setPrev(last);
        }
        catch(...)
        {
            if(!this->head)
            {
                this->initHead(data);
            }
        }
    }
    void removeFrom(const int id)
    {
        NodeT *last = &*this->head;
        register int i = 0;
        while(last&&last->getNext()&&i < id)
        {
            last=last->getNext();
            i++;
        }
        if(last==&*this->head)
        {
            this->head.reset(this->head->getNext());
        }
        else delete last;
    }

    void printListContents(){
        Node<t> *h = &*this->head;
        std::cout<<"---List<"<<typeid(t).name()<<"> start---"<<"\n";
        while(h){
            h->printNode();
            h=h->getNext();
        }
        std::cout<<"---List end---"<<"\n";
    }

    ~List(); //It doesnt matter if I define or declare this directly it 
             //always throws the same errors (+/- appropriate not found 
             //errors because of the missing code)
};

#endif // LIST_H_INCLUDED

错误如下:

(omitted)\compiler\lib\gcc\mingw32.1.0\include\c++\bits\stl_pair.h|113|error: use of deleted function 'List<std::__cxx11::basic_string<char> >::List(const List<std::__cxx11::basic_string<char> >&)'|

(omitted)\entitysystem\list.h|6|note: 'List<std::__cxx11::basic_string<char> >::List(const List<std::__cxx11::basic_string<char> >&)' is implicitly deleted because the default definition would be ill-formed:|

(omitted)\entitysystem\list.h|6|error: use of deleted function 'std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = Node<std::__cxx11::basic_string<char> >; _Dp = std::default_delete<Node<std::__cxx11::basic_string<char> > >]'|

(omitted)\bits\unique_ptr.h|356|note: declared here|

现在我明白了:

(omitted)\entitysystem\list.h|6|note: 'List<std::__cxx11::basic_string<char> >::List(const List<std::__cxx11::basic_string<char> >&)' is implicitly deleted because the default definition would be ill-formed:|

应该是问题的关键,但是我不明白

  1. 和析构函数有什么关系(我是这么想的 如果你做了一些暗示你想使用的事情就会发生 新标准就像实施移动构造函数?)
  2. 为什么它会特别需要那个构造函数?
  3. 我该如何解决?

我已经将我的整个项目暂时上传到 hastebin,所以你可以玩一下。我觉得这个问题嵌套在系统中,所以我不知道我可以从项目中省略多少。如果您需要更小的东西,请询问。我确实从项目中排除了 "instanceCounted.h",因为它只是一个计算实例的模板 class。如果你需要它,我可以添加它

无论如何我希望你能帮助我。

项目如下:https://hastebin.com/ayiquxepic.cpp

由于我想改进我的风格,还请提供反馈。

根据cppreference:

Implicitly-declared move constructor

If no user-defined move constructors are provided for a class type (struct, class, or union), and all of the following is true:

  • there are no user-declared copy constructors;
  • there are no user-declared copy assignment operators;
  • there are no user-declared move assignment operators;
  • there are no user-declared destructors;

then the compiler will declare a move constructor as a non-explicit inline public member of its class with the signature T::T(T&&).

定义析构函数后,还必须定义移动构造函数,以便使用它代替复制构造函数。

当你在ComponentTable的addList函数中实例化一个std::pair时,移动构造函数用于将它插入到std::unordered_map中。定义析构函数意味着不再隐式声明移动构造函数,因此编译器会尝试使用已被删除的复制构造函数。