sla*_*oie 10 c++ shared-ptr weak-ptr
我有一组Creature对象,使用std::make_shared和创建并拥有在我的应用程序的一部分中std::shared_ptr.
我还跟踪一个选择的零个或一个Creature在World使用对象std::weak_ptr<Creature>.
void World::SetSelection(const std::shared_ptr<Creature>& creature) {
selection = creature;
}
std::shared_ptr<Creature> World::GetSelection() const {
return selection.lock();
}
Run Code Online (Sandbox Code Playgroud)
调用者GetSelection负责检查指针是否为空.如果是,那意味着目前没有选择.
这一切都完全符合我的喜好:当选定Creature的自然原因(应用程序中的其他地方)死亡时,再次GetSelection开始返回nullptr,就像没有选择任何东西一样.
但是在这种情况下,World::selection成员仍然指向std::shared_ptr控制块.这可能非常大,因为我std::make_shared用来创建我的Creature对象(我意识到Creature对象在正确的时间被正确销毁但仍然分配了它的内存).我正在考虑GetSelection改为:
std::shared_ptr<Creature> World::GetSelection() {
const auto ret = selection.lock();
if (!ret)
selection.reset();
return ret;
}
Run Code Online (Sandbox Code Playgroud)
一旦我注意到它不再需要,它就会释放内存.令人讨厌的是,这个版本GetSelection不可能const.
GetSelection在这种情况下哪个版本被认为是最佳做法?
如果在模板化代码中发生类似的事情,那么答案是否会改变,哪些sizeof(T)是未知的并且可能是巨大的?或者在C++ 14中std::make_shared<T[]>可能涉及到什么?
如果第二个版本总是最好的,那么理由是什么,std::weak_ptr<T>::expired而lock不是自己做?
首先应该注意的是, 的放置策略std::make_shared是可选的,即标准不强制执行这种优化。这是一个不具约束力的要求,这意味着完全符合要求的实现可能会选择放弃它。
回答您的问题:
鉴于您似乎只有一种选择(并且您不会因保留许多这些控制块而导致内存使用膨胀),我主张保持简单。内存是瓶颈吗?这对我来说是微优化。您应该编写更简单的代码,您可以在其中应用const,然后在需要时返回并进行优化。
答案不会无条件地改变,它会根据问题领域和瓶颈所在而改变。如果您分配一个“巨大”的对象(例如一百千字节),并且该对象的空间在相对未使用的控制块中闲置直到被替换,那么这可能不是您的瓶颈,并且可能不值得编写更多代码(本质上更容易出错、难以维护和破译)来“解决”。
正如std::weak_ptr::lock和std::weak_ptr::expired一样const,根据 C++11 的解释const,它们必须是线程安全的。因此,给定一些,同时调用和 的std::weak_ptr任意组合一定是安全的。在底层,它存储一个指向控制块的指针,它通过它来检查/递增/等等。原子计数器来确定对象是否已过期,或者查看它是否可以获得锁。如果您想在 内部实现优化,则必须以某种方式检查控制块的状态,然后在指针已过期时自动删除指向控制块的指针。这会导致每次访问 时产生开销(即使可以简单地使用原子来完成,它仍然会有开销),所有这些都是为了进行小的优化。lock()expired()std::weak_ptrstd::weak_ptrstd::weak_ptr
| 归档时间: |
|
| 查看次数: |
1463 次 |
| 最近记录: |