在这个shared_ptr示例中有一些不清楚的地方

Something unclear in this shared_ptr example

本文关键字:不清楚 shared ptr      更新时间:2023-10-16
#include <iostream>
#include <boost/shared_ptr.hpp>
class implementation
{
public:
    ~implementation() { std::cout <<"destroying implementationn"; }
    void do_something() { std::cout << "did somethingn"; }
};
void test()
{
    boost::shared_ptr<implementation> sp1(new implementation());
    std::cout<<"The Sample now has "<<sp1.use_count()<<" referencesn";
    boost::shared_ptr<implementation> sp2 = sp1;
    std::cout<<"The Sample now has "<<sp2.use_count()<<" referencesn";
    sp1.reset();
    std::cout<<"After Reset sp1. The Sample now has "<<sp2.use_count()<<" referencesn";
    sp2.reset();
    std::cout<<"After Reset sp2.n";
}
int main()
{
    test();
}

运行结果如下:

$ ./a.out 
The Sample now has 1 references
The Sample now has 2 references
After Reset sp1. The Sample now has 1 references
destroying implementation
After Reset sp2.

请检查以上代码。首先我不明白的是下面这句话是什么意思?sp1是一个指针?一个函数?还是指向函数的指针?new implementation()代表什么?sp1()的参数?

boost::shared_ptr<implementation> sp1(new implementation());

第二个问题是destroying implementationsp1.reset()sp2.reset()的结果。但是如果sp1.reset()被注释掉,那么结果将是:

$ ./a.out 
The Sample now has 1 references
The Sample now has 2 references
After Reset sp1. The Sample now has 2 references
After Reset sp2.
destroying implementation

如果我们只注释掉sp2.reset(),那么结果将是:

$ ./a.out 
The Sample now has 1 references
The Sample now has 2 references
After Reset sp1. The Sample now has 1 references
After Reset sp2.
destroying implementation

所以没有必要调用sp1.reset()sp2.reset()来释放shared_ptr,我对吗?

我不明白的第一件事是下面的句子是什么意思?sp1是一个指针?一个函数?还是指向函数的指针?

spshared_ptr<implementation>。如果您不知道这是什么意思,可以参考参考文档和教程。但简短的版本是:它是一个类似于implementation *指针的对象,除了它会在完成implementation对象时自动删除它。这就是为什么它是一个"智能指针"。shared_ptr是一种特定类型的智能指针,它允许您创建任意数量的副本,并且仅在所有副本消失时才删除底层对象。

这样做的一种方式是,它提供了一种简单形式的垃圾收集,不需要垃圾收集器。

另一种看待它的方式是作为资源获取即初始化(RAII)的一部分,RAII是c++的中心习惯用法之一。

和new implementation()意味着什么?sp1()的参数?

new implementation()创建一个新的implementation对象,调用其默认构造函数,并返回一个implementation *指针。该指针是shared_ptr构造函数的实参。这意味着sp1成为指向新的implementation对象的智能指针,因此当sp1和后来对它的任何副本都消失时,该对象将被销毁和删除。

第二个问题是销毁实现是sp1.reset()和sp1.reset()的结果。

实际上,它是sp1sp2指向新值被销毁的结果。reset做了前者,但只是什么都不做,让他们离开范围做了后者。这是RAII的一个主要部分。

所以没有必要调用sp1.reset()和sp1.reset()来释放shared_ptr,我对吗?

。很少需要显式调用reset。RAII的要点在于你不需要手动管理这些东西;你初始化一个对象(比如shared_ptr)来获得对资源的访问权,然后让这个对象离开来释放访问权。

在一些情况下它是有用的。例如,如果您有一个shared_ptr作为对象的成员,并且该对象将持续比它拥有的资源长得多的时间,您可以通过调用reset提前释放它。(如果你在此期间把副本传给了别人,你不必担心它会被提前删除——这只意味着你不再参与保持它的存在。)

正如在评论中指出的那样,有一些基础知识需要从SO格式中学习。

然而,最后一个问题值得回答:

所以没有必要调用sp1.reset()和sp1.reset()来释放shared_ptr,我对吗?

如果您只重置一个指针,则您看到实现被破坏的原因是由于作用域结束,即从test()返回-导致shared_ptr s超出作用域并被销毁,从而导致托管对象的销毁。