C++ C++;Direct X sprite类,向量问题

C++ C++;Direct X sprite类,向量问题,c++,directx,sprite,vector,C++,Directx,Sprite,Vector,因此,我使用LPD3DXSPRITE创建了一个精灵类来保存精灵。它工作得很好,直到我把它用在向量中。当向量创建一个副本并销毁另一个精灵时,问题就会出现。当它这样做时,它调用析构函数,它调用LPD3DXSPRITE对象的释放。当这个对象被销毁时,副本不能再调用它,我得到一个内存错误 我该怎么做?我在考虑一个解决方案,让副本指向原件,然后如果没有指向的话指针将变为null,这表明析构函数应该杀死精灵,但这似乎有点疯狂 我已经包括了下面的一些代码。还请注意,我还在学习C++(我是一个C程序员),所以如

因此,我使用LPD3DXSPRITE创建了一个精灵类来保存精灵。它工作得很好,直到我把它用在向量中。当向量创建一个副本并销毁另一个精灵时,问题就会出现。当它这样做时,它调用析构函数,它调用LPD3DXSPRITE对象的释放。当这个对象被销毁时,副本不能再调用它,我得到一个内存错误

我该怎么做?我在考虑一个解决方案,让副本指向原件,然后如果没有指向的话指针将变为null,这表明析构函数应该杀死精灵,但这似乎有点疯狂

我已经包括了下面的一些代码。还请注意,我还在学习C++(我是一个C程序员),所以如果你看到任何疯狂的,请让我知道,而不是离开我。 雪碧

#ifndef SPRITE_H
#define SPRITE_H

#include <d3dx9.h>

// 
class Sprite
    {
    private:
        LPD3DXSPRITE sprite;
这就是我所说的

Testground.h

#ifndef TESTGROUND_H
#define TESTGROUND_H
#include "Console.h"
#include "Log.h"
#include "sprite.h"
#include <string>
#include "Animation.h"
#include <map>
#include <vector>

class TestGround
{
private:
    std::vector<Sprite> sprites;

<强>更新< /强>:我的最初答案是C++语言的东西和复制。现在我看到底层对象是COM对象,所以有更多的方法来解决它

问题是您的Sprite类持有指向Direct3D Sprite的原始指针,该Sprite是COM对象。如果复制了精灵的实例,则现在有两个对象具有指向同一COM对象的指针。如果其中一个精灵被销毁,它会销毁COM对象,剩下的精灵会留下一个悬空的指针

当向量需要增长时,可能会发生这种复制。向量分配空间并将对象复制(或移动)到新空间,然后销毁原始副本。(移动是C++11的一项功能,您也需要做一些工作才能支持它。)

COM对象是按引用计数的,因此在上一版本之前不应销毁它们。但参考计数的负担落在你身上。复制精灵时,需要增加相应D3DXSprite对象中的引用计数

选项1:您可以通过实现Sprite复制构造函数并让它在指针上调用AddRef来直接实现这一点

Sprite::Sprite(const Sprite &_copy) :
  center(_copy.center),
  color(_copy.color),
  // blah blah blah
  sprite(_copy.sprite)
{
  sprite->AddRef();
}
选项2:使用智能指针管理引用计数。我发现
中的
ATL::CComPtr
对此非常有效

#include <atlbase.h>

class Sprite {
   // blah blah blah
   private:
     ATL::CComPtr<ID3DXSprite> sprite;
};
#包括
雪碧{
//废话废话
私人:
ATL::CComPtr sprite;
};
现在您甚至不必实现复制构造函数。编译器将为您制作一个复制每个成员的文件。复制CComPtr时,它会为您增加引用计数。当您的Sprite被销毁时,CComPtr将减少引用计数(因此您不再需要~Sprite析构函数——或者,如果需要,它将不再调用Sprite->Release()

我的原始答案如下,这些也是有效的选择

备选案文1。如果您使用的是C++11,请为Sprite实现move构造函数和move赋值操作符,然后像现在这样将Sprite直接放入std::vector中

备选案文2。使您的精灵不可复制(通过使用
=delete
声明复制构造函数和赋值运算符,或者通过将它们声明为私有而不实现它们)。然后让你的向量持有指向精灵的智能指针(例如,
std::vector


备选案文3。让您的精灵复制构造函数和复制赋值操作符进行深度复制——也就是说,创建一个新的
LPD3DXSPRITE
,其设置方式与源对象中的设置方式相同。使用这种方法,您可以将它们直接放入std::vector。

请编辑您的问题并删除所有与问题无关的代码。这里不是进行代码审查的地方:)我会缩小范围,这是我最后一次因为没有真正的代码而被骂,所以我不确定这里的正确程序是什么。似乎我只是不能正确的是什么是正确的程序。只是有最低数量的代码需要重现的问题。您可以假设我们知道您的inlcudes和类似内容是正确的,因为代码是编译的。我从来没有这样想过,我想这将是游戏编程而不仅仅是概念。如果今晚我得不到答复,我就换个职位。谢谢。您没有粘贴密钥代码,您是在哪里创建副本的?你在哪里摧毁了另一个物体?将代码粘贴到出现问题的地方。谢谢。我已经在这上面呆了一两个月了。我一回到家就实施这个。
Sprite::Sprite(const Sprite &_copy) :
  center(_copy.center),
  color(_copy.color),
  // blah blah blah
  sprite(_copy.sprite)
{
  sprite->AddRef();
}
#include <atlbase.h>

class Sprite {
   // blah blah blah
   private:
     ATL::CComPtr<ID3DXSprite> sprite;
};