#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,我是对的吗?
答案 0 :(得分:2)
我不清楚的第一件事是下面的句子是什么意思?那么sp1是一个指针?一个功能?或指向函数的指针?
sp
是shared_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()而导致破坏实现。
实际上,由于sp1
和sp2
指向新值或被销毁,因此给出了它。 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
超出范围并被销毁因此导致了管理目标的破坏。