你的问题是你正在这一行复制你的纹理
graphic_grid = Texture(renderer, "gfx/grid.bmp");
由于您没有定义复制赋值运算符或移动赋值,因此编译器为您提供了一个,它只是按原样复制成员。
一旦临时创建Texture(renderer, "gfx/grid.bmp");
被摧毁,graphic_grid.texture
不再有效。您可以通过摆脱您的Texture
析构函数,你应该发现一切都按预期工作(当然你不actually想要这样做,这不是解决办法)。
您将需要实现移动赋值或复制赋值构造函数,如果您的情况最好是前者Texture
s 并不意味着被复制(并且由于您需要分配,您还应该提供一个移动/复制构造函数,以及按照五规则的其他两个移动/复制方法,或者至少明确地delete
them).
请仔细阅读0/3/5的规则
C++11 中的“三法则”变成了“五法则”? https://stackoverflow.com/questions/4782757/rule-of-three-becomes-rule-of-five-with-c11
如果您使用的是 GCC-Weffc++
flag 会警告您像这样的狡猾的类设计的某些部分。
就我个人而言,我尝试尽可能地将句柄和指针包装到 RAII 类型中,只要每个成员对其自身负责,您通常不必浪费时间使用复制和移动构造函数。std::unique_ptr
对此效果很好,例如:
template<typename T, void(*destroy)(T*), typename Ptr = std::unique_ptr<T, decltype(destroy)>>
struct Handle : public Ptr
{
Handle(T*&& p): Ptr{p, destroy}
{
if (!*this)
throw std::runtime_error{SDL_GetError()};
}
};
using Window_h = Handle<SDL_Window, SDL_DestroyWindow>;
using Surface_h = Handle<SDL_Surface, SDL_FreeSurface>;
// And so on for other handles
可以如下使用
Window_h window{SDL_CreateWindow(
"Hello world",
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
800, 600,
0
)};
如果你要包裹SDL_Texture
如上所述,那么你的Texture
类将有一个隐式移动构造函数和移动赋值运算符,它们可以开箱即用(您必须摆脱renderer
然而,成员,或者以不同的方式处理它,例如将其设为std::shared_ptr
因此它不会与纹理一起被破坏,除非它的引用计数为 0)。
您的代码还有一些其他奇怪的事情,例如从构造函数过早返回。如果无法构造对象,则应该抛出异常。