4

考虑以下向量:

std::vector<std::shared_ptr<X>> myVector;

以及将给定元素添加到向量的以下两个函数:

void foo1(std::shared_ptr<X> x)
{
    myVector.push_back(x);
}

void foo2(const std::shared_ptr<X>& x)
{
    myVector.push_back(x);
}

我的理解是,这两个函数都将 a 推shared_ptrX向量中,从而增加X. 第一个函数导致引用计数的额外增加和减少,但这是不必要的。

我的理解正确吗?因此,第二种选择更可取吗?

4

3 回答 3

3

您应该将函数重写为:

void foo1(std::shared_ptr<X> x)
{
    myVector.emplace_back(std::move(x));
}

void foo2(const std::shared_ptr<X>& x)
{
    myVector.emplace_back(x);
}

那么这两个版本应该更有效,哪一个取决于情况和特定的编译器,如果有的话,很可能差异会非常小。

于 2015-11-05T15:52:43.157 回答
3

foo1您按值传递参数(即共享指针)时。因此,复制构造函数 ofstd::shared_ptr<X>将被调用(即,当在}of调用本地副本的析构函数时,引用计数器将增加然后减少foo1)。

在您通过引用foo2传递参数(即共享指针) 。const因此,您传递了const原始对象的限定别名(即,不会增加 ref 计数器)。

您还可以在以下示例中看到这一点:

struct X {};

void foo1(std::shared_ptr<X> x) { 
  std::cout << "count in foo1(): " << x.use_count() << std::endl;
}

void foo2(const std::shared_ptr<X>& x) {
  std::cout << "count in foo2(): " << x.use_count() << std::endl;
}

int main() {
  std::shared_ptr<X> x(new X);
  std::cout << "count in main(): " << x.use_count() << std::endl;
  foo1(x);
  foo2(x);
}

输出:

count in main(): 1
count in foo1(): 2
count in foo2(): 1

如您所见foo1,不同的 shared_ptr 实例的数量为 2。这是在 中shared_ptr定义的原始main和在 中的副本foo1。而在foo2ref 计数器中仍然为 1。

因此,你的推理是正确的。

于 2015-11-05T20:04:25.557 回答
0

通常最好通过引用传递共享指针,因为原子增量往往会降低性能。在您的情况下,它不会引起注意,因为无论如何您都在复制它。

于 2015-11-05T15:59:03.283 回答