将对象传递给期望shared_ptr的函数,而不实际共享所有权

时间:2012-08-26 05:06:40

标签: c++ memory-management shared-ptr

首先,我确实意识到这与shared_ptr的目的完全矛盾。我正在处理一些库代码,其中ParticleSystem的实例期望在构造期间将shared_ptr传递给它们以设置用于每个粒子的纹理。问题是,我已经以我的纹理具有混凝土所有权的方式构建了我的程序的其余部分(如果这是正确的术语) - TextureCache拥有所有纹理。所以我需要一种方法来处理这个ParticleSystem类,而不允许它删除我的纹理。如果我只是简单地创建一个像ParticleSystem(std::shared_ptr<Texture>&myTexture)这样的新实例,那么它会在破坏时破坏纹理(这是一个不需要的和无效的操作,因为我的纹理甚至没有使用new创建) 。

我看到这个问题最简洁的方法是这样的:

  1. 创建一个shared_ptr,在创建ParticleSystem的函数中保存纹理。
  2. 然后使用placement new,将shared_ptr重建在与刚刚创建的shared_ptr相同的内存位置。纹理现在的引用计数为2.
  3. 创建粒子系统。
  4. 让shared_ptr超出范围。它的解构函数将被调用,因为它是在堆栈上分配的,它只会将引用计数递减1.因此,对象的引用计数总是比实际值大1,因此它永远不会被自动销毁。
  5. 我相信这个解决方案听起来很合理,但它仍然感觉非常黑暗。有没有更好的方法来解决我的问题?

4 个答案:

答案 0 :(得分:5)

如果你想将非托管指针(由你自己管理)传递给期望智能指针的代码,例如shared_ptr,你可以通过创建空的但不是空的{{1}来禁用«智能»指针功能。通过别名构造函数:

shared_ptr

此解决方案比其他人建议的自定义删除器更有效,更短,因为没有控制块分配和引用计数。

可在此处找到一些其他详细信息:

What is the difference between an empty and a null std::shared_ptr in C++?

How to avoid big memory allocation with std::make_shared

答案 1 :(得分:3)

您可以使用custom deleter that does nothing创建shared_ptr。这样可以防止删除此shared_ptr所拥有的纹理。

struct null_deleter
{
    void operator()(void const *) const
    {
    }
};

shared_ptr<Texture> CreateTexture(Texture* myTexture)
{
    shared_ptr<Texture> pTexture(myTexture, null_deleter());
    return pTexture;
}

答案 2 :(得分:1)

shared_ptr允许您提供自定义删除工具。所以shared_ptr可以用于内存分配malloc或你正在使用的任何内存分配方案,你甚至可以用它来自动解锁互斥锁或关闭文件,但我离题了。您可以创建一个带有空删除器的shared_ptr,当它的引用计数达到0时,它将不会执行任何操作。

答案 3 :(得分:0)

按照Vaughn Cato的建议,将shared_ptr存储在您的缓存中。为了在没有人使用它时从缓存中删除纹理,只需检查use_count的{​​{1}}函数是否返回shared_ptr,这意味着缓存是唯一的所有者