共享指针的复制和交换效率

Copy&Swap efficiency for shared pointers

本文关键字:交换 效率 复制 指针 共享      更新时间:2023-10-16

这可以被视为对例如为什么共享指针赋值;交换';?。

问题是关于复制&交换习语,例如在助推中使用。

我确实理解Copy&Swap是重用现有代码,以避免重复和错误。但有2种情况(实际上1种可以减少到另一种(不是最佳的:

  1. 智能指针实例相同
  2. 包含的指针相同

对于shared_ptr,ref计数器是原子递增的,对于intrusive_ptr(仅限升压(,它们可能是原子递增。因此,副本的成本很高。

如果分配的实现方式如下:,这是可以避免的

smart_ptr& operator=(const smart_ptr& other){
if(this->ptr_ == other.ptr_) return *this;
smart_ptr(other).swap(*this); // I assume I can simply do this here, right?
return *this;
}
smart_ptr& operator=(smart_ptr&& other){
smart_ptr(std::move(other)).swap(*this);
return *this;
}

这不是最快、最安全的实现吗?还是有我没有看到的问题?

如果它是最快的,为什么boost或stdlib不使用它?

澄清第2点。考虑以下代码:

smart_ptr a(new foo);
auto b = a;
...
// Eventually:
a = b;

这是而不是作为&a != &b的自分配。副本&交换确实涉及对引用计数器的不必要修改。

自分配不是常见的情况,因此每次测试它的成本会更高,然后以任何一种方式进行交换。此外,复制指针基本上是可以执行的最快的复制。

复制shared_ptr的实际成本是原子引用增量(可能涉及在下面使用互斥(。

如果你真的想测试这两种方法的性能,我建议你使用谷歌基准库,写一组测试用例(用于自我分配和所有其他用例(并对其进行测量。记住,优化器现在可以用你的代码来优化它。如果不进行测量,很难判断这是否更快,但我想如果是相当昂贵的版本没有它是更好的:(

编辑:

如果你不想增加引用计数(这是复制shared_ptr的昂贵部分(,你可以总是使用移动构造函数:

smart_ptr a(new foo);
auto b = a;
...
// Eventually:
a = std::move(b);