1
#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 implementation的结果。但是如果被注释掉,那么结果将是:sp1.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,对吗?

4

2 回答 2

2

我首先不清楚的是,下面的句子是什么意思?那么 sp1 是一个指针吗?一个函数?还是指向函数的指针?

sp是一个shared_ptr<implementation>。如果您不知道这意味着什么,可以查看参考文档和教程。但简短的版本是:它是一个行为类似于implementation *指针的对象,除了它会在implementation您完成对象时自动删除它。这就是使它成为“智能指针”的原因。Ashared_ptr是一种特定类型的智能指针,可让您制作任意数量的副本,并且仅在所有这些副本消失时才删除底层对象。

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

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

和 new implementation() 意味着什么?sp1() 的论点?

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

第二个问题是 sp1.reset() 和 sp2.reset() 的结果是破坏实现。

实际上,它是两者的结果,sp1sp2指向新值或被破坏。reset前者是这样做的,但后者只是什么都不做,让它们超出范围。这是 RAII 的主要部分。

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

确切地。您很少想显式调用reset. RAII 的全部意义在于您不必手动管理这些事情。您初始化一个对象(如 a shared_ptr)以获取对资源的访问权限,然后让该对象离开以释放访问权限。

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

于 2013-01-01T07:50:54.267 回答
1

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

但是,最后一个问题值得回答:

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

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

于 2013-01-01T07:55:46.903 回答