首先,我确实意识到这完全违背了 shared_ptr 的目的。我正在处理一些库代码,其中 ParticleSystem 的实例希望在构造期间将 shared_ptr 传递给它们以设置用于每个粒子的纹理。问题是,我已经以我的纹理具有具体所有权(如果这是正确的术语)的方式构建了我的程序的其余部分 - TextureCache 拥有所有纹理。所以我需要一种方法来使用这个 ParticleSystem 类,而不允许它删除我的纹理。如果我只是创建一个像 ParticleSystem(std::shared_ptr<Texture>&myTexture)
这样的新实例然后它会在纹理被破坏时尝试破坏它(这是一个不需要的和无效的操作,因为我的纹理甚至不是用 new
创建的)。
我看到解决这个问题的最干净的方法是这样的:
- 在创建 ParticleSystem 的函数中创建一个保存纹理的 shared_ptr。
- 然后使用 placement new 在与我刚创建的 shared_ptr 相同的内存位置重建 shared_ptr。纹理现在的引用计数为 2。
- 创建粒子系统。
- 让 shared_ptr 超出范围。它的解构函数将被调用,因为它是在堆栈上分配的,它只会将引用计数减 1。因此,该对象的引用计数将始终比实际值大 1,因此它永远不会被自动销毁。
我相信这个解决方案是合理的,但它仍然令人难以置信的骇人听闻。有没有更好的方法来解决我的问题?
最佳答案
如果您想将非托管指针(您自己管理的)传递给需要智能指针的代码,例如 shared_ptr
,您可以通过创建空的但非空的来禁用“智能”指针功能shared_ptr
通过别名构造函数:
Texture* unmanagedPointer = ...
shared_ptr<Texture> smartPointer(shared_ptr<Texture>(), unmanagedPointer);
这个解决方案比其他人建议的自定义删除器更高效、更短,因为没有控制 block 分配和引用计数正在进行。
一些额外的细节可以在这里找到:
What is the difference between an empty and a null std::shared_ptr in C++?
关于c++ - 将对象传递给期望 shared_ptr 的函数而不实际共享所有权,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12127758/