繁体   English   中英

删除函数unique_ptr的使用

[英]Use of deleted function unique_ptr

我有一个使用唯一指针向量的实体类。 出于某种原因,它给出了以下错误:

错误日志:

In file included from /usr/include/c++/8/vector:62,
                 from ./RactorUtils.h:8,
                 from ./OpenGLRenderer.h:4,
                 from ./TestGame.cpp:2:
/usr/include/c++/8/bits/stl_construct.h: In instantiation of ‘void std::_Construct(_T1*, _Args&& ...) [with _T1 = std::unique_ptr<IComponent>; _Args = {const std::unique_ptr<IComponent, std::default_delete<IComponent> >&}]’:
/usr/include/c++/8/bits/stl_uninitialized.h:83:18:   required from ‘static _ForwardIterator std::__uninitialized_copy<_TrivialValueTypes>::__uninit_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = __gnu_cxx::__normal_iterator<const std::unique_ptr<IComponent>*, std::vector<std::unique_ptr<IComponent> > >; _ForwardIterator = std::unique_ptr<IComponent>*; bool _TrivialValueTypes = false]’
/usr/include/c++/8/bits/stl_uninitialized.h:134:15:   required from ‘_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = __gnu_cxx::__normal_iterator<const std::unique_ptr<IComponent>*, std::vector<std::unique_ptr<IComponent> > >; _ForwardIterator = std::unique_ptr<IComponent>*]’
/usr/include/c++/8/bits/stl_uninitialized.h:289:37:   required from ‘_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, std::allocator<_Tp>&) [with _InputIterator = __gnu_cxx::__normal_iterator<const std::unique_ptr<IComponent>*, std::vector<std::unique_ptr<IComponent> > >; _ForwardIterator = std::unique_ptr<IComponent>*; _Tp = std::unique_ptr<IComponent>]’
/usr/include/c++/8/bits/stl_vector.h:463:31:   required from ‘std::vector<_Tp, _Alloc>::vector(const std::vector<_Tp, _Alloc>&) [with _Tp = std::unique_ptr<IComponent>; _Alloc = std::allocator<std::unique_ptr<IComponent> >]’
./ECS/ECS.h:42:7:   required from here
/usr/include/c++/8/bits/stl_construct.h:75:7: error: use of deleted function ‘std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = IComponent; _Dp = std::default_delete<IComponent>]’
     { ::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...); }
       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/8/memory:80,
                 from ./ECS/ECS.h:6,
                 from ./RactorUtils.h:23,
                 from ./OpenGLRenderer.h:4,
                 from ./TestGame.cpp:2:
/usr/include/c++/8/bits/unique_ptr.h:394:7: note: declared here
       unique_ptr(const unique_ptr&) = delete;
       ^~~~~~~~~~

实体类

class IEntity{
private:
    bool active = true;
    vector<unique_ptr<IComponent>> components;
    ComponentArray componentArray;
    ComponentBitset componentBitset;

public:
    const char* name;

    template<typename T> bool hasComponent(){
        return componentBitset[getComponentTypeID<T>()];
    }

    template<typename T> T& addComponent(){
        T c;
        unique_ptr<T> uPtr(&c);
        components.emplace_back(move(uPtr));

        componentArray[getComponentTypeID<T>()] = &c;
        componentBitset[getComponentTypeID<T>()] = true;

        return *move(uPtr);
    }

    template<typename T> T& getComponent() const{
        auto ptr(componentArray[getComponentTypeID<T>()]);
        return *static_cast<T*>(ptr);
    }
};

我知道无法复制唯一指针,但我不知道在哪里复制它。

编辑:通过将以下代码添加到 IEntity,我实际上得到了它被复制的位置:

explicit IEntity();
IEntity(const IEntity&) = delete;
IEntity& operator= (const IEntity&) = delete;
~IEntity() = default;

但是现在它在下面给出的函数中显示错误:

//Prototype
void UniformCaller(void (*ptr)(IEntity object, Shader shader), IEntity object, Shader shader);

//Call
void Render(IEntity object, glm::mat4x4 projectionMatrix, glm::mat4x4 viewMatrix){
Shader* shader = object.getComponent<MeshRenderer>().shader;
UniformCaller(shader->uniform_callback, object, *shader);
}

//Definition
void UniformCaller(void (*ptr)(IEntity object, Shader shader), IEntity object, Shader shader){
    (*ptr) (object, shader);
}

Edit2:正如评论中所指出的,我将它们全部更改为引用,现在我收到一个奇怪的错误,如下所示:

/usr/bin/ld: /tmp/ccPzMwMa.o: in function `ComponentManager::createComponent(IComponent*)':
TestGame.cpp:(.text._ZN16ComponentManager15createComponentEP10IComponent[_ZN16ComponentManager15createComponentEP10IComponent]+0x41): undefined reference to `ComponentManager::components'
/usr/bin/ld: /tmp/ccPzMwMa.o: in function `EntityManager::addEntity()':
TestGame.cpp:(.text._ZN13EntityManager9addEntityEv[_ZN13EntityManager9addEntityEv]+0x6c): undefined reference to `EntityManager::entities'
collect2: error: ld returned 1 exit status

添加实体():

static IEntity& addEntity(){
        IEntity* e = new IEntity();
        unique_ptr<IEntity> uPtr(e);
        entities.emplace_back(move(uPtr));
        return *move(uPtr);
}

创建组件():

static IComponent& createComponent(IComponent* component){
        unique_ptr<IComponent> ptr(component);
        components.emplace_back(move(ptr));
        return *move(ptr);
}

你的代码有很多问题。 首先, unique_ptr用于delete堆分配的内存。 您正在堆栈上创建T实例,获取一个地址并将该地址提供给unique_ptr - 这是错误的,并且会在调用删除器时导致崩溃。

其次,正如评论中指出的那样,您正在存储对局部变量的引用,该变量将在函数返回时终止,因此您最终会得到一个悬空引用。

此外,您在一个std::unique_ptr上两次调用std::move ,这是错误的,因为在第一次std::move调用之后,指针将为nullptr

要解决这些问题,请在堆上而不是在堆栈上分配T

template<typename T> T& addComponent() {
    T* c = new T(); // Normally, you'd want to avoid this (naked new) but since
                    // we don't know what componentArray is, we can't know why
                    // you need to store the raw pointer, too.
    components.emplace_back(c);
    componentArray[getComponentTypeID<T>()] = c;
    componentBitset[getComponentTypeID<T>()] = true;

    return *c;
}

现在,您向我们展示的错误恰好位于您没有向我们展示的代码中; 您正在尝试复制components - std::vector<std::unique_ptr<T>> ,这表明您正在尝试复制整个班级。 尽管如此,您可以通过使用std::shared_ptr<T>而不是std::unique_ptr<T>来解决此问题,但这只是一个快速而肮脏的解决方案。 你真的应该找到你试图复制你的IEntity类的地方,并弄清楚是否有办法摆脱这个不需要的副本。

暂无
暂无

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

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