在我的代码中,我有一个动态分配的普通指针
class Texture
{
//code...
SDL_Texture* m_texture;
};
我从Texture类中分配了SDL_Texture *的Init()函数,并且析构函数释放了内存。
然而,事实证明这是一个问题。我不得不使用shared_ptr,因为我对不同的对象使用相同的纹理,这将被破坏,因此不允许我正确地显示它们(在矢量的第一个对象被破坏之后,纹理(对于所有相同类型的对象共享) )已经不见了。)
所以我决定使用shared_ptr,但我遇到了一个问题 - 我不知道如何为shared_ptr分配一些东西:
//Old code:
m_texture = loadTexture();
//New code:
class Texture
{
std::shared_ptr<SDL_Texture> m_texture;
};
//code...
m_texture = loadTexture(); // Error! No assignment operator
我尝试过.get()函数,但它是rvalue,所以我不能给它分配任何东西。有什么想法吗?
提前致谢。
答案 0 :(得分:4)
您也需要自定义删除器:
#include <memory>
// Fake SDL library
typedef void SDL_Texture;
SDL_Texture* SDL_CreateTextureFromSurface(/*SDL_Renderer* , SDL_Surface* */) {
return 0;
}
void SDL_DestroyTexture(SDL_Texture* texture)
{}
// Shared
typedef std::shared_ptr<SDL_Texture> SharedTexture;
inline SharedTexture make_shared(SDL_Texture* texture) {
return SharedTexture(texture, SDL_DestroyTexture);
}
int main() {
SharedTexture texture;
texture = make_shared(SDL_CreateTextureFromSurface());
}
请注意,C库:
答案 1 :(得分:3)
std::shared_ptr
不允许您直接为其指定普通指针。当你想到的时候,有相当令人信服的理由不允许它隐含地发生。首先,shared_ptr
需要分配一个(外部的,一般的)引用计数器。例如,考虑以下(假设的)代码:
std::shared_ptr<A> p1 = obj;
std::shared_ptr<A> p2 = obj;
当指针超出范围时会发生什么?每个作业都会创建自己的引用计数器,因为p2
无法知道p1
创建的作业。实际上,obj
被删除两次 - UB。
首选解决方案是使用库函数std::make_shared
。与包装外部创建的对象相比,它提供了许多好处:
另一种选择是从shared_ptr
派生由std::enable_shared_from_this
管理的课程。这些对象将必要的结构保存为数据成员,因此保留了make_shared
的第一个好处。此外,以第一个示例中描述的方式初始化shared_ptr
变得有效,因为构造函数/复制赋值运算符可以识别std::enable_shared_from_this
子类并使用内部结构进行簿记,因此p1
p2
1}}和obj
将使用存储在shared_ptr
内的相同参考计数器。
但是,有时候,在这种情况下,不可能使用上述任何策略。如果您确实需要直接设置reset()
,则有一种方法可以执行此操作 - shared_ptr
。但请谨慎使用它,并确保尽快将指针包裹在{{1}}中,然后让它管理它。特别是我认为良好的做法是在方法中封装这种资源的创建,并且永远不要将包装的指针暴露在它之外。