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

时间:2018-07-30 11:13:08

标签: c++ smart-pointers copy-and-swap

这可以看作是对例如Why shared pointer assignment does 'swap'?

问题是关于e.g. in boost使用的“复制和交换”习惯用法。

我确实了解复制和交换的好处是重用了现有代码,从而避免了重复和错误。但是有2种情况(实际上是1种可以减少为另一种)不是最佳的情况:

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

对于shared_ptr,引用计数器会自动递增;对于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。复制和交换确实涉及对引用计数器的不必要的修改。

1 个答案:

答案 0 :(得分:0)

自我分配并不常见,因此每次进行测试然后再以任何一种方式进行交换都会花费更多。同样,复制指针基本上是一个人可以执行的最快复制。

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

如果您真的想测试这两种方法的性能,建议您使用google benchmark库并编写一组测试用例(用于自定义和所有其他用例)并进行测量。请记住,这些天的优化器可以使您的代码对其进行优化感到惊奇。如果不进行度量,很难确定它是否更快,但我想如果没有它,该版本似乎很昂贵:)

编辑:

如果您不想引用计数增加(这对于复制shared_ptr来说是昂贵的部分),则可以始终使用move构造函数:

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