【问题标题】:How to insert elements into a multidimensional vector of unique pointers?如何将元素插入到唯一指针的多维向量中?
【发布时间】:2017-04-25 11:35:32
【问题描述】:

我有一个带有 _rounds 私有成员的 Turn 类。 _rounds 是指向另一个名为 Animation 的类的 std 唯一指针的二维 std 向量:

Turn.h

std::vector<std::vector<std::unique_ptr<Animation>>> _rounds;   

Animation.h

class Animation
{
public:
    enum Type
    {
        MOVE,
        ATTACK,
        DIE,
        FADEOUT,
        MAX_TYPES
    };

//Constructors
Animation();        
Animation(Creature* creature, Animation::Type type, GameManager* gameManager, const std::function<void()> callback = nullptr);

//Getters   
const int& getOriginRowClipsIndex() { return _originRowClipsIndex; }
bool& getFinished() { return _finished; }
Type& getType() { return _type; }
Creature& getCreature() { return *_creature; }

//Setters       
void setOriginRowClipsIndex(int originRowClipsIndex) { _originRowClipsIndex = originRowClipsIndex; }

void animate(); 
void reset();
SDL_Rect* getClip(int index) {      
    return &_clips[index];      
}

private:
    GameManager* _gameManager;
    Creature * _creature;
    bool _finished;
    unsigned int _clipIndex;
    int _frequency;
    int _originRowClipsIndex; //Origin index of anim clips.     
    std::vector<SDL_Rect> _clips;   
    Type _type; 
    std::function<void()> _callback;
};
#endif

我从代码的各个点动态分配动画,并尝试使用名为 addAnimation 的 Turn 公共方法将它们添加到 Turn _rounds,如下所示:

auto animation = std::make_unique<Animation>(this, Animation::Type::MOVE, _gameManager);            
turn.addAnimation(std::move(animation)); //Use move to make addAnimation take ownership of the animation.

然后 Turn addAnimation() 方法尝试将动画添加到其成员 _rounds 中,如下所示:

Turn.cpp

void Turn::addAnimation(std::unique_ptr<Animation> animation)
{   
unsigned int roundIndex;

//Set animating to true when the first animation is added to the first animation round. TODO: Move this elsewhere.
if (_rounds.size() == 0)
    _animating = true;

if (animation->getType() == Animation::MOVE) { //All move animations go on first round.
    roundIndex = 0;
    if (animation->getCreature().isPlayer()) //Set _playerMoves to be able to set monster attacks on the correct round index.
    {
        _playerMoves = true;
    }
}else if (animation->getType() == Animation::ATTACK) 
{
    roundIndex = _playerMoves ? _nAttacks + 1 : _nAttacks;
    _nAttacks++; //Increment number of attacks.     
}
else
{
    roundIndex = _rounds.size();
}

//Check if the wanted round index already exists and create if not.
if (roundIndex >= _rounds.size()) {
    //_rounds.push_back({});
    _rounds.resize(_rounds.size() + 1);
}

//Add animation to animations vector.
_rounds[roundIndex].push_back(std::move(animation));
}

但是我收到一条错误消息,提示我正在尝试引用已删除的函数,就好像我在尝试使用已删除的复制构造函数或其他东西一样。

> 1>------ Build started: Project: Roguelike, Configuration: Debug Win32 ------
1>  Turn.cpp
1>c:\program files (x86)\microsoft visual studio 14.0\vc\include\xmemory0(637): error C2280: 'std::unique_ptr<Animation,std::default_delete<_Ty>>::unique_ptr(const std::unique_ptr<_Ty,std::default_delete<_Ty>> &)': attempting to reference a deleted function
1>          with
1>          [
1>              _Ty=Animation
1>          ]
1>  c:\program files (x86)\microsoft visual studio 14.0\vc\include\memory(1435): note: see declaration of 'std::unique_ptr<Animation,std::default_delete<_Ty>>::unique_ptr'
1>          with
1>          [
1>              _Ty=Animation
1>          ]
1>  c:\program files (x86)\microsoft visual studio 14.0\vc\include\xmemory0(755): note: see reference to function template instantiation 'void std::allocator<_Ty>::construct<_Objty,std::unique_ptr<Animation,std::default_delete<Animation>>&>(_Objty *,std::unique_ptr<Animation,std::default_delete<Animation>> &)' being compiled
1>          with
1>          [
1>              _Ty=std::unique_ptr<Animation,std::default_delete<Animation>>,
1>              _Objty=std::unique_ptr<Animation,std::default_delete<Animation>>
1>          ]
1>  c:\program files (x86)\microsoft visual studio 14.0\vc\include\xmemory0(755): note: see reference to function template instantiation 'void std::allocator<_Ty>::construct<_Objty,std::unique_ptr<Animation,std::default_delete<Animation>>&>(_Objty *,std::unique_ptr<Animation,std::default_delete<Animation>> &)' being compiled
1>          with
1>          [
1>              _Ty=std::unique_ptr<Animation,std::default_delete<Animation>>,
1>              _Objty=std::unique_ptr<Animation,std::default_delete<Animation>>
1>          ]
1>  c:\program files (x86)\microsoft visual studio 14.0\vc\include\xmemory0(894): note: see reference to function template instantiation 'void std::allocator_traits<_Alloc>::construct<_Ty,std::unique_ptr<Animation,std::default_delete<Animation>>&>(std::allocator<_Ty> &,_Objty *,std::unique_ptr<Animation,std::default_delete<Animation>> &)' being compiled
1>          with
1>          [
1>              _Alloc=std::allocator<std::unique_ptr<Animation,std::default_delete<Animation>>>,
1>              _Ty=std::unique_ptr<Animation,std::default_delete<Animation>>,
1>              _Objty=std::unique_ptr<Animation,std::default_delete<Animation>>
1>          ]
1>  c:\program files (x86)\microsoft visual studio 14.0\vc\include\xmemory0(893): note: see reference to function template instantiation 'void std::allocator_traits<_Alloc>::construct<_Ty,std::unique_ptr<Animation,std::default_delete<Animation>>&>(std::allocator<_Ty> &,_Objty *,std::unique_ptr<Animation,std::default_delete<Animation>> &)' being compiled
1>          with
1>          [
1>              _Alloc=std::allocator<std::unique_ptr<Animation,std::default_delete<Animation>>>,
1>              _Ty=std::unique_ptr<Animation,std::default_delete<Animation>>,
1>              _Objty=std::unique_ptr<Animation,std::default_delete<Animation>>
1>          ]
1>  c:\program files (x86)\microsoft visual studio 14.0\vc\include\vector(1286): note: see reference to function template instantiation 'void std::_Wrap_alloc<std::allocator<_Ty>>::construct<std::unique_ptr<Animation,std::default_delete<Animation>>,std::unique_ptr<Animation,std::default_delete<Animation>>&>(_Ty *,std::unique_ptr<Animation,std::default_delete<Animation>> &)' being compiled
1>          with
1>          [
1>              _Ty=std::unique_ptr<Animation,std::default_delete<Animation>>
1>          ]
1>  c:\program files (x86)\microsoft visual studio 14.0\vc\include\vector(1285): note: see reference to function template instantiation 'void std::_Wrap_alloc<std::allocator<_Ty>>::construct<std::unique_ptr<Animation,std::default_delete<Animation>>,std::unique_ptr<Animation,std::default_delete<Animation>>&>(_Ty *,std::unique_ptr<Animation,std::default_delete<Animation>> &)' being compiled
1>          with
1>          [
1>              _Ty=std::unique_ptr<Animation,std::default_delete<Animation>>
1>          ]
1>  c:\program files (x86)\microsoft visual studio 14.0\vc\include\vector(1278): note: while compiling class template member function 'void std::vector<std::unique_ptr<Animation,std::default_delete<_Ty>>,std::allocator<std::unique_ptr<_Ty,std::default_delete<_Ty>>>>::push_back(const std::unique_ptr<_Ty,std::default_delete<_Ty>> &)'
1>          with
1>          [
1>              _Ty=Animation
1>          ]
1>  c:\cpp\roguelike\roguelike\turn.cpp(44): note: see reference to function template instantiation 'void std::vector<std::unique_ptr<Animation,std::default_delete<_Ty>>,std::allocator<std::unique_ptr<_Ty,std::default_delete<_Ty>>>>::push_back(const std::unique_ptr<_Ty,std::default_delete<_Ty>> &)' being compiled
1>          with
1>          [
1>              _Ty=Animation
1>          ]
1>  c:\cpp\roguelike\roguelike\turn.cpp(44): note: see reference to class template instantiation 'std::vector<std::unique_ptr<Animation,std::default_delete<_Ty>>,std::allocator<std::unique_ptr<_Ty,std::default_delete<_Ty>>>>' being compiled
1>          with
1>          [
1>              _Ty=Animation
1>          ]
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

我的代码中唯一出现在模板错误长链末尾的点是指向 addAnimation 的唯一指针向量的 push_back。

如果我尝试编译一个简化的案例,即使将自定义构造函数添加到 Animation 类也没有问题:

#include "stdafx.h"
#include <iostream>
#include <vector>
#include <memory>

class Animation
{
    int _animation_value;
public:
    Animation() {};
    Animation(int animation_value)
        : _animation_value(animation_value)
    {}
};

class Turn
{
    std::vector<std::vector<std::unique_ptr<Animation>>> _rounds;
public:
    void addAnimation(std::unique_ptr<Animation> round)
    {
        _rounds.resize(_rounds.size() + 1);
        _rounds[0].push_back(std::move(round));
    }
};

class Other
{
public:
    void foo()
    {
        auto x = std::make_unique<Animation>(7);
        Turn turn;
        turn.addAnimation(std::move(x));
    }
};

int main()
{
    Other other;
    other.foo();        
    return 0;
}

有什么帮助吗?

【问题讨论】:

  • 你能发Turn代码吗?
  • 请发布实际的错误信息。释义时经常会丢失重要信息。 minimal reproducible example 也不会受到伤害。
  • @molbdnilo 为什么他使用复制构造函数? std::vector::push_back(T&& value) 是有效的重载。为什么实现回退到复制值?
  • 保存您的项目状态。把它备份。现在开始删除代码。每次删除后重建以确认错误仍然发生。当您确认它仍然发生时备份项目,然后重复并删除更多代码。第一轮很简单:将addAnimation 减少到错误来自的那一行。重建。还是报错?继续,进行备份,也许从项目中删除整个文件。不会出错?返回上次备份并删除其他地方的代码。您不关心运行时。您不关心链接器错误。您只想在 minimal reproducible example 中重现相同的构建错误
  • 您的目标是一个文件,其中包含少于 20 行代码。理想情况下,通过 命令行 调用 cl.exe 并使用已知的最小命令行参数。但是你不要跳到那个;你减少到确保你在减少时不会丢失错误。在此过程中,您可能会发现原因,或者发现它需要两个文件(!)或其他东西,但这就是您的目标。

标签: c++ c++11 smart-pointers unique-ptr


【解决方案1】:

你是否在代码中的任何地方复制你的轮到类?因为,如 cmets 所述,addAnimation 函数本身似乎没有错误。所以也许你生成了一些代码,其中整个转弯类都被复制了,所以唯一指针向量的向量想要复制?

【讨论】:

  • 我能找到的唯一类似的事情是 Turn 对象也是另一个类的成员,并且该类有一个 getter 方法用于转弯:Turn&amp; getTurn() { return _turn; } 也许我应该使用 shared_ptr 而不是 unique_ptr?
  • 1.确定如果您使用 shared_pointers,问题就会消失。但这不是我们/你想要的。 shared_pointers 不像 unique_pointers 那样轻量级,我建议使用 unique_pointers,如果它们真的代表你所得到的。 (如果你想分享你的实例,他们当然会使用 shared_ptr) 2. 你的 getTurn 方法似乎很好,因为你不复制你的轮次实例。但是一旦你复制了你的轮次实例并且你不编写自己的复制例程,编译器就会想要复制向量。并且由于您无法复制 unique_ptr ,因此您会收到错误消息。
  • @HarleyFuagras “好的,摆弄我发现了问题。在 Turn 构造函数中,我正在使用 _rounds = {}; 初始化轮向量。删除该行可以解决问题,但我不太明白为什么。 "我可能是错的,但我猜是因为您在 initializer_list 的帮助下创建了一个空的唯一指针向量,并且该列表将被复制到作业中。即使列表为空,副本的代码也必须是可编译的(只是猜测。但它会有意义)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-06-09
  • 2012-12-05
  • 1970-01-01
  • 1970-01-01
  • 2011-03-30
  • 1970-01-01
  • 2014-09-12
相关资源
最近更新 更多