考虑此程序:
#include <memory>
struct T {
T() {}
};
void do_something(std::shared_ptr<T> ptr) {
// Do something with ptr; might or might not leave
// other copies of ptr in other variables of the
// program
}
int main() {
std::shared_ptr<T> ptr = std::make_shared();
do_something(ptr);
// ptr might or might not be the only owner
ptr = std::make_shared();
return 0;
}
第二次执行make_shared
时,ptr
可能具有或可能具有其他共享所有者,这取决于运行时do_something
中发生的情况。如果没有其他对象,则ptr
会在分配或构造同一时间的新对象时或多或少地破坏并释放其先前拥有的对象。有什么方法可以避免分配和取消分配,并使用同一区域来构造新对象? (此处的目标是优化对分配器的两次调用)
我当然同意在破坏旧对象之后再构造新的T
对象,而在上面的代码中则相反。因此,我想使用类似ptr.replace<U>(args)
的方法来执行以下操作:减少ptr
的引用计数;如果计数为零,则没有其他弱引用,并且U
是ptr
内容的最派生类型,它将破坏拥有的对象,并使用参数{{1 }}在同一内存区域中,避免调用内存分配器。否则,其行为类似于args
。
是否有必要使用当前的标准库执行此优化?
答案 0 :(得分:2)
没有机制可以计算weak_ptr
个共享对象的数量。您只能查询强计数(通过shared_ptr::use_count
)。请注意,在多线程环境中,允许将其作为近似计数(即使用memory_order_relaxed
负载)。
您确定这是性能瓶颈吗?
答案 1 :(得分:1)
考虑allocate_shared
。它使用分配器创建一个shared_ptr
。可以将释放的shared_ptr的控制块缓存在分配器中,并在下一个allocate_shared
调用中立即重用它,保存一个delete和new。
我怀疑这会带来很大的不同。在多线程应用程序中,此分配器对于获取快速和正确的消息来说可能很简单。