这可以被视为对例如为什么共享指针赋值;交换';?。
问题是关于复制&交换习语,例如在助推中使用。
我确实理解Copy&Swap是重用现有代码,以避免重复和错误。但有2种情况(实际上1种可以减少到另一种(不是最佳的:
- 智能指针实例相同
- 包含的指针相同
对于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);