引用 std::shared:ptr 以避免引用计数



我经常面临这样的争论,即通过接受const std::shared_ptr<T>&可以避免引用计数增加:

void foo(std::shared_ptr<const int> p); 
void foo2(const std::shared_ptr<const int>& p); 
int main(){
std::shared_ptr<const int> a = std::make_shared<int>(3);
foo(a);  // calling this function always does reference counting (atomic locks...)
foo2(a); // calling this function elides reference counting
std::shared_ptr<int> b = std::make_shared<int>(3);;
foo2(b); // what happens here? since there is a cast involved creating a temporary ... (NRVO??)
}

但是我认为在调用foo2(b)时没有省略引用计数?但是,编译器或 std 实现能否以某种方式避免引用计数。如果foo2(std::move(b))被召唤,让这种省略发生,会不会更好?

是的,在进入foo2之前必然会有引用计数增加,在退出之前必然会减少。这是因为参数const std::shared_ptr<const int>& p必须引用类型为std::shared_ptr<const int>的不同对象,因此必须构造和销毁一个临时对象。

在语言中,不可能省略此引用计数,因为如果在执行foo2期间修改了参数b,则参数p必须不受影响;它必须继续指向堆上的同一int对象,该对象可以修改但不能删除。(当foo2a一起调用时,这不适用,因为在这种情况下,p直接指a,而不是临时的,因此对a的修改可以通过p可见。

std::move(b)传递给foo2不是一个好主意,因为这会将b留空,并在临时绑定到p时删除int对象。

std::shared_ptr<const int>是与std::shared_ptr<int>不同的类型,但有一个隐式转换构造函数。

当你调用foo2(b)时,一个临时std::shared_ptr<const int>是由b构造的,并绑定到p。构造函数递增引用计数,析构函数递减引用计数。

当您调用foo1(a)时,a会复制到p中。p在调用期间存在,然后被销毁。构造函数递增引用计数,析构函数递减引用计数。

当你调用foo2(a)时,a绑定到p。不会构造临时,因此不会更改引用计数。

请注意,您的示例中没有引用计数,因为任何指针都没有指向ints 或const ints。

最新更新