我试图理解共享指针的以下哪种用法在将其插入向量时更有意义。bar
接受共享指针的常量引用,而foo
接受副本。在这两种情况下,传入的参数都被移动到一个向量中。有趣的是,调用者中a
的use_count
对于foo
和bar
仍然为2,这意味着向量存储了一个“副本”?
就像shared_ptr是由一个引用传递的,它的计数不会递增,一旦它被“移动”到一个vector中,它就会递增,这是否意味着vector没有存储对原始对象a
的引用?
class A
{
std::vector<std::shared_ptr<int>> _vec;
public:
void bar(const std::shared_ptr<int>& ptr)
{
_vec.emplace_back(std::move(ptr));
}
void foo(std::shared_ptr<int> ptr)
{
_vec.emplace_back(std::move(ptr));
}
};
int main()
{
auto sp = std::make_shared<int>();
A a;
// a.foo(sp); // use_count = 2
a.bar(sp); // use_count = 2
}
2条答案
按热度按时间nfg76nw01#
通过引用
const
将shared_ptr
传递给bar
,这意味着不能通过该引用修改原始的shared_ptr
。从
share_ptr
移动需要修改moved-fromshared_ptr
以将其设置为不指向任何内容。看到问题了吗?
bar
不能从ptr
移动,所以它最终将其复制到向量中。ptr
/sp
仍然有效,并继续指向您在main
中分配的int
,a._vec
也持有相同int
的shared_ptr
。因此use_count
必须为2。如果你真的想从
sp
移走,那么你应该修改bar
以接受某种可变的引用,尽管你真的应该让它接受一个右值引用,因为a.bar(sp)
导致sp
无效会违背大多数程序员的期望:Demo
这限制了调用者总是将他们的
shared_ptr
移动到A
中,当调用者想要放弃所有权时,像在foo
中那样简单地通过值接受参数可能不会导致可测量的性能差异,而当他们不想放弃所有权时,则提供更大的灵活性。k7fdbhmy2#
在这两种情况下,传递给foo和bar的共享指针都被移动到了vector中,这意味着vector获得了共享指针管理的动态分配内存的所有权,而调用者中的共享指针不再管理任何内存。
foo和bar的区别在于foo获取共享指针的副本,而bar获取共享指针的常量引用。由于foo获取副本,因此共享指针的引用计数在传递给foo时会递增1。这意味着在foo被调用后,引用计数将为2。
相反,bar采用对共享指针的常量引用,因此引用计数在传递给bar时不递增。这意味着引用计数在调用bar后将保持为1。
总的来说,在这种情况下使用bar更有效,因为它不需要额外增加引用计数,但实际上性能上的差异可能很小。更重要的是,要为您的特定用例选择可读性和可维护性更强的方法。