优化替换共享指针内容时对分配器的调用
Optimize calls to allocator when replacing the content of a shared pointer
考虑这个程序:
#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
内容派生最多的类型,它会破坏拥有的对象,并使用args
在同一内存区域中的参数构造一个新对象,从而避免调用内存分配器。否则它的行为就像ptr = std::make_shared<U>(args)
.
是否可以使用当前标准库执行此优化?
没有计算共享对象weak_ptr
数的机制。只能查询强计数(通过shared_ptr::use_count
)。请注意,在多线程环境中,这允许是近似计数(即使用memory_order_relaxed
负载)。
您确定这是性能瓶颈吗?
考虑allocate_shared
。它使用分配器创建shared_ptr
。可以将释放shared_ptr的控制块缓存在分配器中,并立即在下一次allocate_shared
调用中重用它,从而保存删除和新建。
我怀疑这会有很大的不同。在多线程应用程序中,此分配器可以快速且正确。
相关文章:
- 什么时候调用组成单元对象的析构函数
- 对RValue对象调用的LValue ref限定成员函数
- 为什么使用 "this" 指针调用派生成员函数?
- 函数调用中参数的顺序重要吗
- OpenGL - 在抛出"__gnu_cxx::recursive_init_error"实例后终止调用?
- c++ 中的自定义分配器,用于不调用secure_string实现
- 在抛出"std::__cxx11::basic_string<char、std::char_traits<char>、std::分配器<char>>"的实例后调用终
- 为什么这个自定义分配器的析构函数在 GCC/MSVS 的 stdlib 中被调用两次
- 在调用中使用 std::vector,<double>但收到有关 std::vector<double、std::分配器>正在使用的错误<double>
- std::cout 如果从自定义分配器 (Visual Studio 2019) 调用,则不会输出
- 不调用带有 std::vector 的自定义分配器
- 优化替换共享指针内容时对分配器的调用
- 在分配器感知类调用复制构造函数中对向量元素的引用
- forward_list,设置,列表等如何调用标准::分配器
- 使用自定义分配器调用对象构造函数/析构函数
- 通过从自定义分配器调用 deassigned 引发的不明原因异常
- 为什么std::list要不带参数地调用我的分配器?
- 调用分配器.构造基元
- 永远不要直接调用 std::分配器的成员函数是最佳做法吗?
- 如果容器和分配器都是同一内存池的一部分,我还需要调用std::容器的析构函数吗?