了解传递给函数时 shared_ptr 引用计数何时递增

Understanding when shared_ptr reference counts are incremented when passing into a function

我有以下Containerclass

template <typename T>
class Container
{
private:
    std::vector<std::shared_ptr<T>> items_;
public:
    void addItem(std::shared_ptr<T> item)
    {
        std::cout << "useCount addItem pre: " << item.use_count() << std::endl;
        items_.push_back(std::move(item));
        std::cout << "useCount addItem post: " << item.use_count() << std::endl;
    }
};

我是这样称呼它的

int main(int argc, char** argv) {
    std::unique_ptr<Container<std::string>> container = std::make_unique<Container<std::string>>();

    std::shared_ptr<std::string> s = std::make_shared<std::string>("hello");

    std::cout << "useCount main pre: " << s.use_count() << std::endl;

    container->addItem(s);

    std::cout << "useCount main post: " << s.use_count() << std::endl;

    return 0;
}

这是我得到的输出

useCount main pre: 1
useCount addItem pre: 2
useCount addItem post: 0
useCount main post: 2

逐行...

  1. 有道理,一旦定义 s 就只有一个引用

  2. 有道理,s 被复制到 item 所以它的引用计数增加 1

  3. 我已将 item 的所有权授予 items_,因此引用计数不应更改,因为 addItem 已放弃所有权并将其转让给 items_。我希望引用计数为 2,一次来自 main,一次来自 items_。相反它是 0.

  4. 有意义,只要一个引用来自 main,一个引用来自 items_

感谢您的澄清!

移动共享指针后,它应该是空的。空共享指针的使用次数为0.

从另一个角度来看,您期望 mainitems_ 拥有该对象(这是正确的),但如果将它们计入 use_count 的指针 item,则共有三个共享指针拥有该对象。这与您对 2 的期望相矛盾。当然,这可以通过 item 不再拥有该对象这一事实来解释,因此它的使用计数实际上不再与拥有它的其他指针相关。

std::move 将项目从那个变量移到另一个变量中。正如一位作者所说,它“has explicit license to pillage [the variable]." For , that puts the original object into an unspecified state. However, it appears 因为它使对象处于空状态。

所有这一切归结为您不能再将 item 视为对 s 的相同引用。它处于不同的状态,存储着别的东西。这就是您的引用计数关闭的原因。

如果你这样做了:

std::cout << "useCount addItem post: " << items_.back().use_count() << std::endl;

您将获得 2 的预期输出。