C++ 直接X精灵类,矢量问题
C++ Direct X sprite class, problems with vector
所以我创建了一个精灵类,使用LPD3DXSPRITE来保存精灵。 它的效果很棒,直到我在矢量中使用它。 当矢量创建副本并销毁其他精灵时,就会出现问题。 当它这样做时,它会调用析构函数,该析构函数要求释放LPD3DXSPRITE对象。 当这个对象被销毁时,副本无法再调用它,并且我收到内存错误。
我该如何解决这个问题? 我正在考虑一种解决方案,涉及让副本指向原件,然后如果没有什么可指向的,指针将变为空,表明析构函数应该杀死精灵,但这似乎有点疯狂。
我在下面包含了一些代码。 另外请注意,我仍在学习C++(我的职业是 C# 程序员),所以如果你看到任何疯狂的东西,请告诉我,不要对我大发雷霆。
雪碧.h
#ifndef SPRITE_H
#define SPRITE_H
#include <d3dx9.h>
//
class Sprite
{
private:
LPD3DXSPRITE sprite;
雪碧.cpp
#include "sprite.h"
// Copy constructor
Sprite::Sprite(Sprite &_copy)
{
center = _copy.center;
color = _copy.color;
matrix = _copy.matrix;
position = _copy.position;
rotation = _copy.rotation;
scale = _copy.scale;
sourceRect = _copy.sourceRect;
sprite = _copy.sprite;
texture = _copy.texture;
}
// Full constructor which fully initializes the sprite.
Sprite::Sprite(LPDIRECT3DDEVICE9 _device, LPDIRECT3DTEXTURE9 _texture)
{
Initialize(_device,_texture);
}
Sprite::~Sprite()
{
sprite->Release();
}
// Initializes values and creates the sprite
void Sprite::Initialize(LPDIRECT3DDEVICE9 _device, LPDIRECT3DTEXTURE9 _texture)
{
Initialize();
// Set our variables
texture = _texture;
// If we don't succeed throw an error so we know things
// got ****ed up somehow
if (!SUCCEEDED(D3DXCreateSprite(_device, &sprite)))
{
throw("Sprite creation failed");
}
SetCenter();
SetSourceRect();
}
// Sets initial values for the sprite
void Sprite::Initialize()
{
// Sets variable to default
}
这就是我称之为的地方。
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;
这里有一些测试场.cpp
试验场.cpp
#include "TestGround.h"
TestGround::TestGround(LPDIRECT3DDEVICE9 _device)
{
sprites.emplace_back(_device, tBank["TestTexture"]);
更新:我最初的答案是C++语言的东西和复制。 现在我看到基础对象是一个 COM 对象,因此有更多方法可以解决它。
问题是你的 Sprite 类持有指向 Direct3D 精灵的原始指针,这是一个 COM 对象。 如果复制了 Sprite 的实例,现在有两个对象具有指向同一 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:使用智能指针管理引用计数。 我发现<atlbase.h>
ATL::CComPtr
对此效果很好。
#include <atlbase.h>
class Sprite {
// blah blah blah
private:
ATL::CComPtr<ID3DXSprite> sprite;
};
现在你甚至不必实现复制构造函数。 编译器将通过制作一个复制每个成员的成员来为您执行此操作。 复制 CComPtr 时,它会增加引用计数。 当你的精灵被销毁时,CComPtr 会减少引用计数(因此你不再需要你的 ~Sprite 析构函数——或者,如果你这样做,它就不应该再调用精灵->Release())。
我最初的答案如下,这些也是有效的选择。
选项 1. 如果您使用的是 C++11,请实现 Sprite 的移动构造函数和移动赋值运算符,然后像现在一样将精灵直接放入 std::vector 中。
选项 2. 使你的 Sprite 不可复制(通过使用= delete
声明复制构造函数和赋值运算符,或者将它们声明为私有而不实现它们)。 然后让你的矢量包含指向你的精灵的智能指针(例如,std::vector<std::shared_ptr<Sprite>>
)。
选项 3. 使 Sprite 复制构造函数和复制赋值运算符执行深层复制,即创建一个与源对象中的LPD3DXSPRITE
相同的新。 使用这种方法,您可以将它们直接放入 std::vector 中。
- 警告处理为错误这里有什么问题
- 最小硬币更换问题(自上而下方法)
- 为"adjacent"变量赋值时出现问题
- 我的神经网络不起作用 [XOR 问题]
- 在Ubuntu 16.04上安装Cilk时出现问题
- C++我的数学有什么问题,为什么我的代码不能正确循环
- 编译包含字符串的代码时遇到问题
- Project Euler问题4的错误解决方案
- 问题:什么是QAbstractItemView::NoEditTriggers的反面
- 在编译C++代码(具有dlib和opencv)到WASM时面临问题
- 在进程中对同一管道进行读取和写入时C++管道出现问题
- 静态数据成员的问题-修复链接错误会导致编译器错误
- 我想直接在结构中插入,但没有一种方法可以正确避免填充问题
- 直接丢失或间接丢失 - 瓦尔格林德问题
- 测试项目在访问私有静态方法时遇到问题,尽管我从未直接调用过它
- 从直接多元传播变为间接的问题时可能会出现什么问题
- C++ 直接X精灵类,矢量问题
- 卷曲字符串附加问题,curl_formadd C++读取带有额外字符的变量,但直接CURLFORM_COPYNAME工作正常,"key" [?
- 直接使用C++WinRT组件或C++XAML项目是否存在任何性能问题
- 当函数在头文件中列出时,未定义的引用,但如果我直接复制和粘贴代码则没问题