这个shared_ptr示例中有些不清楚的东西

时间:2013-01-01 07:43:39

标签: c++ boost

#include <iostream>
#include <boost/shared_ptr.hpp>

class implementation
{
public:
    ~implementation() { std::cout <<"destroying implementation\n"; }
    void do_something() { std::cout << "did something\n"; }
};

void test()
{
    boost::shared_ptr<implementation> sp1(new implementation());
    std::cout<<"The Sample now has "<<sp1.use_count()<<" references\n";

    boost::shared_ptr<implementation> sp2 = sp1;
    std::cout<<"The Sample now has "<<sp2.use_count()<<" references\n";

    sp1.reset();
    std::cout<<"After Reset sp1. The Sample now has "<<sp2.use_count()<<" references\n";

    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,我是对的吗?

2 个答案:

答案 0 :(得分:2)

  

我不清楚的第一件事是下面的句子是什么意思?那么sp1是一个指针?一个功能?或指向函数的指针?

spshared_ptr<implementation>。如果您不知道这意味着什么,请参考参考文档和教程。但是短版本是:它是一个类似于implementation *指针的对象,除了它会自动删除你完成它的implementation对象。这就是它成为“智能指针”的原因。 shared_ptr是一种特定类型的智能指针,可让您根据需要制作任意数量的副本,并且只有在所有这些副本都消失后才会删除基础对象。

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

另一种看待它的方式是Resource Acquisition Is Initialization(RAII)的一部分,它是C ++的核心习语之一。

  

和新的实现()意味着什么? sp1()的参数?

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

  

第二个问题是由于sp1.reset()和sp2.reset()而导致破坏实现。

实际上,由于sp1sp2指向新值被销毁,因此给出了它。 reset执行前者,但只是做任何事情并让它们超出范围。这是RAII的重要组成部分。

  

因此没有必要同时调用sp1.reset()和sp2.reset()来释放shared_ptr,我是对的吗?

完全。您很少想要明确调用reset。 RAII的重点是你不必手动管理这些东西;初始化一个对象(如shared_ptr)以获取对资源的访问权限,然后让该对象离开以释放访问权限。

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

答案 1 :(得分:1)

正如评论中指出的那样,从SO格式中可以学到一些基础知识。

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

  

因此没有必要同时调用sp1.reset()和sp2.reset()来释放shared_ptr,我是对的吗?

如果你只重置一个指针,你看到实现被破坏的原因是由于范围的结束,即从test()返回 - 导致你的shared_ptr超出范围并被销毁因此导致了管理目标的破坏。