这可以看作是对例如Why shared pointer assignment does 'swap'?。
问题是关于e.g. in boost使用的“复制和交换”习惯用法。
我确实了解复制和交换的好处是重用了现有代码,从而避免了重复和错误。但是有2种情况(实际上是1种可以减少为另一种)不是最佳的情况:
对于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
。复制和交换确实涉及对引用计数器的不必要的修改。
答案 0 :(得分:0)
自我分配并不常见,因此每次进行测试然后再以任何一种方式进行交换都会花费更多。同样,复制指针基本上是一个人可以执行的最快复制。
复制shared_ptr的实际成本是原子引用增量(可能涉及在下面使用互斥锁)。
如果您真的想测试这两种方法的性能,建议您使用google benchmark库并编写一组测试用例(用于自定义和所有其他用例)并进行测量。请记住,这些天的优化器可以使您的代码对其进行优化感到惊奇。如果不进行度量,很难确定它是否更快,但我想如果没有它,该版本似乎很昂贵:)
编辑:
如果您不想引用计数增加(这对于复制shared_ptr来说是昂贵的部分),则可以始终使用move构造函数:
smart_ptr a(new foo);
auto b = a;
...
// Eventually:
a = std::move(b);