1.shared_ptr允许有多个指针指向同一个对象,unique_ptr独占所指向的对象。
2.类似于vector,智能指针也是模板。创建智能指针:
1 shared_ptr<string> p1; //指向string的shared_ptr
2 shared_ptr<list<int>> p2; //指向int的list的shared_ptr
使用make_shared函数分配一个对象并初始化它,make_shared函数返回一个指向此对象的shared_ptr:
1 //指向值为42的int的shared_ptr
2 shared_ptr<int> p3 = make_shared<int>(42);
3
4 //指向一个值为“999”的string
5 shared_ptr<string> p4 = make_shared<string>("999");
6
7 //指向一个值初始化的int,即值为0
8 shared_ptr<int> p5 = make_shared<int>();
3.我们可以认为每个share_ptr都有一个关联的计数器,通常称为引用计数(reference count)。无论何时我们拷贝一个shared_ptr,计数器都会递增。
例如这些都会使所关联的计数器递增:
(1)当用一个shared_ptr初始化另外一个shared_ptr
(2)将它作为参数传递给另外一个函数
(3)作为函数的返回值
例如这些操作会使计数器都会递减:
(1)给share_ptr赋新的值
(2)share_ptr被销毁
(3)局部的share_ptr离开作用域
以下通过两个例子来讲解计数的规则:
1 shared_ptr<int> p = make_shared<int>(42); 2 shared_ptr<int> q(p); //此对象现在有两个引用者,计数为2 3 shared_ptr<int> r = make_shared<int>(42); //r现在有一个计数 4 r = q; //r现在指向q所指向的对象了,所以第二个42被销毁,因为计数为0 5 //而第一个计数为3 6 cout << "p所指对象的引用计数为:" << p.use_count() << endl;
再比如下一个程序:
1 shared_ptr<Foo> factory(T arg) 2 { 3 return make_shared<Foo>(arg); //返回一个shared_ptr<Foo> 4 } 5 void use_factory(T arg) 6 { 7 shared_ptr<Foo> p = factory(arg); //此时p的计数值为1 8 } //由于p是局部变量,出了这个函数,计数值先递减,然后检查计数值,发现为0,销毁p的对象,内存被释放掉 9 shared_ptr<Foo> use_factory(T arg) 10 { 11 shared_ptr<Foo> p = factory(arg); //此时p的计数值为1 12 return p; //返回了一个智能指针类,计数值加1,为2 13 } //离开了作用域,但是指向的内存不会被释放,因为还有对象的引用计数不是0
4.当指向的最后一个shared_ptr被销毁时,是调用析构函数来完成销毁工作的,析构函数会先递减它所指向的对象的引用计数,再检查引用计数值,如果引用计数变为0,那么shared_ptr析构函数就会销毁对象,并释放它占用的内存。
附:shared_ptr支持的一些操作: