C++ weak_ptr创建性能

标签 c++ performance shared-ptr reference-counting weak-ptr

我已经读到创建或复制std::shared_ptr会涉及一些开销(引用计数器的原子增量等)。

但是如何从中创建std::weak_ptr呢?

Obj * obj = new Obj();
// fast
Obj * o = obj;
// slow
std::shared_ptr<Obj> a(o);
// slow
std::shared_ptr<Obj> b(a);
// slow ?
std::weak_ptr<Obj> c(b);

我希望能够获得更快的性能,但是我知道共享指针仍然必须增加弱引用计数器。
那么,这仍然像将shared_ptr复制到另一个一样慢吗?

最佳答案

除了Alec's非常有趣的描述他以前的项目中使用的shared/weak_ptr系统之外,我还想提供更多有关典型std::shared_ptr/weak_ptr实现可能发生的情况的详细信息:

// slow
std::shared_ptr<Obj> a(o);

上述结构的主要费用是分配一个内存块来保存两个引用计数。此处不需要执行原子操作(除了在operator new下实现可能会或可能不会执行的操作之外)。
// slow
std::shared_ptr<Obj> b(a);

复制结构中的主要费用通常是单个原子增量。
// slow ?
std::weak_ptr<Obj> c(b);

weak_ptr构造函数中的主要开销通常是单个原子增量。我希望该构造函数的性能几乎与shared_ptr复制构造函数的性能相同。

要注意的另外两个重要的构造函数是:
std::shared_ptr<Obj> d(std::move(a));  // shared_ptr(shared_ptr&&);
std::weak_ptr<Obj> e(std::move( c ));  // weak_ptr(weak_ptr&&);

(以及匹配的移动分配运算符)

move构造函数根本不需要任何原子操作。他们只是将引用计数从rhs复制到lhs,并使rhs == nullptr。

仅当在分配之前执行lhs!= nullptr时,移动分配运算符才需要原子减量。在移动分配之前的大部分时间(例如,在vector<shared_ptr<T>>中)lhs == nullptr,因此根本没有原子操作。

后者(weak_ptr move成员)实际上不是C++ 11,但由LWG 2315处理。但是,我希望大多数实现已经实现了它(我知道它已经在libc++中实现了)。

当在容器中搜寻智能指针时,将使用这些移动成员,例如在vector<shared_ptr<T>>::insert/erase下,与使用智能指针拷贝成员相比,可以产生可衡量的积极影响。

我指出这一点是为了让您知道,如果您有机会移动而不是复制shared_ptr/weak_ptr,那么键入一些额外的字符是很麻烦的。

关于C++ weak_ptr创建性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20290524/

相关文章:

c++ - 我在哪里可以看到来自 Visual Studio 2012 中未处理的 std::exception 的 what() 消息?

c++ - 外部变量的问题

javascript - 如何让我的 JavaScript 程序运行得更快?

c++ - 多态树类中的双指针向上转换(再次)、shared_ptr 和通用 setChild 函数

c++ - 如何为通过共享指针在不同模块之间传递的模板类分配内存

c++ - 如果我将 std::shared_ptr 重置为自身会发生什么

c++ - 如何合并 2 个部分排序的数组?

c++ - 如何使用 VC++ 编译器标志指定枚举大小

c# - 引用创建类的不同表现

sql - 运行慢查询的简单 MySQL 表