7

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

我在这个问题上看到的最干净的方法是这样的:

  1. 在创建 ParticleSystem 的函数中创建一个包含纹理的 shared_ptr。
  2. 然后使用placement new,在与我刚刚创建的shared_ptr 相同的内存位置重建shared_ptr。现在纹理的引用计数为 2。
  3. 创建粒子系统。
  4. 让 shared_ptr 超出范围。因为它是在堆栈上分配的,所以它的解构器将被调用,并且它只会将引用计数减 1。因此,对象的引用计数将始终比实际值大 1,因此它永远不会被自动销毁。

我相信这个解决方案是合理的,但它仍然令人难以置信的骇人听闻。有没有更好的方法来解决我的问题?

4

4 回答 4

5

如果您想将非托管指针(您自己管理)传递给需要智能指针的代码,例如,您可以通过别名构造shared_ptr函数创建空但不为空来禁用«智能»指针功能:shared_ptr

Texture* unmanagedPointer = ...
shared_ptr<Texture> smartPointer(shared_ptr<Texture>(), unmanagedPointer);

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

一些额外的细节可以在这里找到:

C++ 中的空 std::shared_ptr 和空 std::shared_ptr 有什么区别?

如何使用 std::make_shared 避免大内存分配

于 2015-04-17T21:43:59.123 回答
3

您可以shared_ptr使用不执行任何操作的自定义删除器创建。这将防止删除 this 拥有的纹理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;
}
于 2012-08-26T07:26:32.913 回答
1

shared_ptr允许您提供自定义删除器。因此shared_ptr可以用于使用 malloc 分配的内存或您正在使用的任何内存分配方案,您甚至可以使用它来自动解锁互斥锁或关闭文件,但我离题了。您可以使用 null 删除器创建一个shared_ptr,当它的引用计数达到 0 时它不会做任何事情。

于 2012-08-26T07:27:41.427 回答
0

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

于 2012-08-26T05:27:51.343 回答