C++ 对象或常量指针的副本?

C++ 对象或常量指针的副本?,c++,class,pointers,game-engine,C++,Class,Pointers,Game Engine,我制作了一个2d游戏引擎,但我怀疑我做事情的一种方式是否是从结构上做事情的最佳方式。例如,Sprite的一个成员可以有多个图形成员。现在,我将这些成员保存在向量(不是std::vector,但为了简单起见,我将在示例中使用它): 我可以创建副本: class Sprite { private: std::vector<Graphic> _graphicList; public: Sprite(); ~Sprite(); void addGraphic(

我制作了一个2d游戏引擎,但我怀疑我做事情的一种方式是否是从结构上做事情的最佳方式。例如,Sprite的一个成员可以有多个图形成员。现在,我将这些成员保存在
向量
(不是
std::vector
,但为了简单起见,我将在示例中使用它):

我可以创建副本:

class Sprite {
private:
    std::vector<Graphic> _graphicList;
public:
    Sprite();
    ~Sprite();
    void addGraphic(Graphic& toAdd); //adds a Graphic to _graphicList
    void draw() const; //draws all items in _graphicList
};
类精灵{
私人:
std::vector\u图形列表;
公众:
雪碧();
~Sprite();
void addGraphic(Graphic&toAdd);//将图形添加到_graphicslist
void draw()const;//在_graphicslist中绘制所有项
};
然而,如果我保持图形在范围内,这将浪费宝贵的内存

所以我想我的问题可以归结为:

在游戏引擎中,更重要的是:健壮或高效的内存使用?

如果你的对象超出了范围,任何使用指针或引用的尝试都会被C++语言标准定义为不明确的行为(意思是,它可能会破坏其他对象,或者它可能会破坏程序,或者杀死你的猫最可怕的方式)。因此,对象是否应该在范围内不是问题——它必须在范围内


同样,健壮性是一种你不想用任何东西来交换的品质。如果您的程序崩溃,用户将不关心它使用的内存有多少。为了优化内存使用中的程序,你应该仔细考虑很多因素——你的程序在哪里使用大部分内存,如何降低这种用法,以及哪些技巧可以用来降低内存占用(例如缓存和大量重用现有对象)。这些因素中的每一个都在很大程度上取决于您的具体计划,因此一般来说,讨论它对于您的具体目的几乎没有用处。

正确性应该是首要考虑因素。使用范围外对象肯定是错误的,您的程序可能会中止/挂起(未定义的行为)

根据您的需要,有一些方法:

  • 复制对象
void addGraphic(const-Graphic&toAdd)

这可能意味着您需要实现深度复制/复制构造函数操作,如果图形对象包含指针,并且您想要它的完美克隆(而不仅仅是指相同的内存)。如果不执行deeep复制,原始对象可能会被释放,而您仍然引用已释放的内存

  • 自己创建对象

只需自己在addGraphic中创建图形对象,然后放入向量中,这样您就拥有了对象,它不会超出范围。

如果您担心内存使用,那么为什么首先要创建本地副本?为什么不一次性全局加载图像,然后向周围的纹理传递指针?@remyable,这是一个非常简化的示例。实际图像只加载一次,但是您可以有许多包含指向实际图像指针的图形对象。我知道它必须在范围内。
//可能不起作用,因为图形超出范围
注释明确指出行为未定义。这似乎是可行的,但这不是保证,也不是好的做法。谢谢你的意见。这就是我所想的,但是在对我的代码库进行如此大的更改之前,我想咨询其他人。但是,如果其他人更改代码库,或者即使我从现在起一年后回到代码库来修复bug并忘记,也有可能出现这种情况。所有需要深度副本的对象都已具有副本构造函数。不将文件路径传递给精灵是一种有意识的设计选择。
void foo (bool redCircle) {
    Sprite sprCircle;
    if(redCircle) {
        Graphic gfxRedCircle("redCircle.bmp");
        sprCircle.addGraphic(&gfxRedCircle);
    }
    else {
        Graphic gfxBlueCircle("blueCircle.bmp");
        sprCircle.addGraphic(&gfxBlueCircle);
    }
    sprCircle.draw(); //would possibly not work, since the Graphic is out of scope
}
class Sprite {
private:
    std::vector<Graphic> _graphicList;
public:
    Sprite();
    ~Sprite();
    void addGraphic(Graphic& toAdd); //adds a Graphic to _graphicList
    void draw() const; //draws all items in _graphicList
};
void addGraphic(const string &bmpName);