分配 std::shared_ptr
Posted
技术标签:
【中文标题】分配 std::shared_ptr【英文标题】:Assigning std::shared_ptr 【发布时间】:2013-09-08 10:54:41 【问题描述】:在我的代码中,我有一个动态分配的普通指针
class Texture
//code...
SDL_Texture* m_texture;
;
我有来自 Texture 类的 Init() 函数分配了 SDL_Texture*,并且析构函数释放了内存。
然而,这被证明是一个问题。我必须使用 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() 函数,但它是右值,所以我不能给它分配任何东西。有什么想法吗?
提前致谢。
【问题讨论】:
试试.reset()方法loadTexture()
返回什么?
其实我在上面写代码时犯了一个小错误(in post),但没关系。代码看起来像 m_texture.reset(SDL_CreateTextureFromSurface(renderer, loadedSurface)); SDL_CreateTextureFromSurfacce 返回 SDL_Texture* PS。因为我尝试使用 .reset(),所以我这样做了:m_texture.reset(SDL_CreateTextureFromSurface(renderer,loadedSurface));还有甜蜜的模板错误,我完全不知道这是什么意思。对不起,糟糕的评论,但我不知道如何格式化它(还)
【参考方案1】:
您也需要一个自定义删除器:
#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 库:
可以使用不透明类型 有自己的删除功能或正在免费使用【讨论】:
【参考方案2】:std::shared_ptr
不允许您直接为其分配普通指针。当您考虑时,有很多令人信服的理由来禁止它隐含地发生。首先,shared_ptr
需要分配一个(通常是外部的)引用计数器。例如,考虑以下(假设的)代码:
std::shared_ptr<A> p1 = obj;
std::shared_ptr<A> p2 = obj;
当指针超出范围时会发生什么?每个分配都会创建自己的引用计数器,因为p2
无法知道p1
创建的引用计数器。实际上,obj
被删除了两次 - UB。
首选的解决方案是使用库函数std::make_shared
。与包装外部创建的对象相比,它提供了许多好处:
另一种选择是从std::enable_shared_from_this
派生由shared_ptr
管理的类。此类对象维护必要的结构作为数据成员,因此保留了make_shared
的第一个好处。此外,以第一个示例中描述的方式初始化shared_ptr
变得有效,因为构造函数/复制赋值运算符可以识别std::enable_shared_from_this
子类并使用内部结构进行簿记,因此p1
和@987654335 @ 将使用相同的引用计数器,存储在 obj
中。
但有时,就像在这种情况下,不可能使用上述任何策略。如果你真的需要直接设置一个shared_ptr
,有一个方法可以做到——reset()
。但是,请谨慎使用它,并确保尽快将指针包装在shared_ptr
中,然后让它管理它。特别是我认为将此类资源的创建封装在一个方法中并且从不将包装的指针暴露在它之外是一种很好的做法。
【讨论】:
''m_texture = std::make_shared以上是关于分配 std::shared_ptr的主要内容,如果未能解决你的问题,请参考以下文章
Tensorflow 耗尽 GPU 内存:分配器 (GPU_0_bfc) 尝试分配内存不足
Linux 内核 内存管理物理分配页 ⑧ ( __alloc_pages_slowpath 慢速路径调用函数源码分析 | 获取首选内存区域 | 异步回收内存页 | 最低水线也分配 | 直接分配 )