使用已删除的功能unique_ptr

Use of deleted function unique_ptr

本文关键字:unique ptr 功能 删除      更新时间:2023-10-16

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

错误日志:

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);
}

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

/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

addEntity((:

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

createComponent((:

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类的位置,并找出是否有办法摆脱这种不需要的副本。