C++ 使用已删除的功能唯一\u ptr

C++ 使用已删除的功能唯一\u ptr,c++,vector,unique-ptr,C++,Vector,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_con

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

错误日志:

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;
       ^~~~~~~~~~
但现在它在下面给出的函数中显示错误:

//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);
}
加法()

static entity&addEntity(){
IEntity*e=新IEntity();
唯一的ptr uPtr(e);
实体。后置(上移(上移));
返回*移动(uPtr);
}
createComponent():

静态IComponent&createComponent(IComponent*component){
唯一的ptr(组件);
组件。后置(移动(ptr));
返回*移动(ptr);
}

您的代码有许多问题。首先,
unique\u ptr
用于
删除堆分配的内存。您正在堆栈上创建
T
实例,获取一个地址并将此地址提供给
unique\u 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;
}
模板T&addComponent(){
T*c=new T();//通常情况下,您会希望避免这种情况(裸新),但因为
//我们不知道什么是componentArray,也不知道为什么
//您还需要存储原始指针。
组件。后装(c);
componentArray[getComponentTypeID()]=c;
componentBitset[getComponentTypeID()]=true;
返回*c;
}

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

你想在某处复制
组件。即在ECS.h的第42行,如错误消息所示。你展示的代码中似乎没有。好吧,副本不在你展示给我们的代码中。您的
addComponent
功能也已中断。首先,引用本地声明的
c
,在函数退出后,指针无效。其次,您可以使用
move
两次。因此,在末尾(segfault)取消引用
nullptr
。@SarojKr Add
IEntity(const IEntity&)=delete
IEntity&operator=(const IEntity&)=delete,然后查看错误说明。@SarojKr到
IEntity
类。它显式删除复制构造和复制分配。然后,编译器应该在您试图复制
IEntity
的位置向您提供更好的错误,而不是深入解释为什么它不能这样做。(虽然在一个完美的世界里,编译器可以不用手动诱使它这么做。)@SarojKr是的,这就是预期的结果。您试图将
IEntity
复制到某个地方,编译器说“您不能这样做”。但它在哪里给出了错误呢?我以为这就是你想知道的!我的第一个猜测是OP在某处返回了一个IEntity对象。“return foo”需要变成一个动作。@MartinBonnersupportsMonica可能是,但在OP向我们展示这部分代码之前,我们无法知道:)
componentArray
componentBitset
分别是std::array和std::bitset。
//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);
}
/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);
}
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;
}