生成指针的vector的完整副本

C++: make full copy of vector of pointers

本文关键字:副本 vector 指针      更新时间:2023-10-16

我正在制作一款c++游戏。我的关卡对象是一个矢量(对象是我的关卡对象的超类)。

我需要在检查点保存这个向量的状态,并在死亡时检索。

所以在关卡开始时,vector (objects)被创建(old_objects)。

如果遇到检查点,old_objects被擦除,对象被重新复制到old_objects。

如果你死了,对象中的数据将被擦除,old_objects将被复制回对象。

我已经尝试了好几种方法,但我不能让它工作。帮助吗?

编辑:我尝试使用虚拟克隆()方法。它抛出超出范围的错误。
class Object {
  public:
    virtual Object* clone() { return new Object(); }
};
class SubObjectA {
  public:
    Object* clone() { return new SubObjectA(datablahblah); }
};
class SubObjectB {
  public:
    Object* clone() { return new SubObjectB(datablahblah); }
};
for (vector<Object*>::iterator it = objects.begin(); it != objects.end(); it++) {
    Object* tempobj = *it;
    old_objects.push_back(tempobj->clone());
}

但我得到的都是老样子:

terminate called after throwing an instance of 'std::out_of_range'
  what():  vector::_M_range_check
This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.

您可以使用Prototype模式并让Object基类声明一个纯virtual clone()方法。然后,在检查点时,只需遍历vector,在指针上调用clone并将它们压入新vector。

这里唯一重要的要求是提供一个存储所有必要信息的深层复制构造函数(或者如果不可能,则提供一个获取所有所需信息的方法)。然后使用该矢量/方法来创建第二个矢量。比如:

class Object
{
    RenderObject * m_Renderable;
    int m_Health;
    float3 m_Position;
    Object(const Object * other) :
       m_Renderable(nullptr),
       m_Health(other->m_Health), 
       m_Position(other->m_Position)
    { };
    Object * GetStorable()
    {
        return new Object(*this);
    }
};

然后存储"检查点",您只需执行:

vector<vector<shared_ptr<Object>>> gCheckpoints;
vector<shared_ptr<Object>> gLevelObjects;
vector<shared_ptr<Object>> checkpoint;
std::for_each(
    gLevelObjects.begin(), gLevelObjects.end(),
    [&](shared_ptr<Object> obj)
    {
        checkpoint.push_back(obj->GetStorable());
    });
gCheckpoints.push_back(checkpoint); // creates a new checkpoint

当检查点恢复时,您将需要重新创建对象的渲染信息;然而,在大多数图形环境中,这是大多数保存系统的要求。

根据你的Object类是如何设置的,你也可以从另一个只包含存储数据的类继承,并简单地存储它,并在必要时从它创建可渲染(class RenderObject : StoredObject { ... };)。

您可以选择以某种方式序列化对象(二进制保存,xml, json)并将其存储到文件(自动保存/快速保存/检查点)或内存中,然后使用常规加载机制加载该特定文件。

最好的方法取决于你的计划是什么以及你的系统是如何设置的,但是这个概念应该提供基本的或给你一个起点。