scoped_ptr
也叫作用域指针,一个指针独占一个动态分配的对象。对应的类名为 boost::scoped_ptr
,它的定义在 boost/scoped_ptr.hpp
中。
与 std::auto_ptr 区别:不能将所指对象的所有权转移到另一个
scoped_ptr。离开定义指针的作用域后,指针所指动态对象的空间将会释放。
源码
boost_1_69_0\boost\smart_ptr\scoped_ptr.hpp
主要有reset 和 swap 方法
简单使用
#include <iostream>
#include <boost/scoped_ptr.hpp>
using namespace std;
class A
{
public:
A(const int num) : val(num) {}
~A()
{
cout << "A destroy" << endl;
}
int val;
};
int main()
{
boost::scoped_ptr<A> ptr1(new A(10));
boost::scoped_ptr<A> ptr2(new A(5));
cout << ptr1->val <<endl;
cout << ptr2->val <<endl;
// swap
ptr1.swap(ptr2);
cout << ptr1->val <<endl;
cout << ptr2->val <<endl;
//ptr1 = ptr2; // 编译不过
//ptr1.reset(ptr1.get()); // 执行出错 Assertion `p == 0 || p != px'
//ptr1.reset(ptr2.get()); // 输出三个 "A destroy"(原因参见reset实现) 但是此时ptr1 和 ptr2 指向相同的地址,释放两次导致出错
ptr1.reset(new A(11)); // 执行成功,输出三个 "A destroy"
return 0;
}
scoped_array
作用域数组,与scoped_ptr 相似。 不同在于,作用域数组的析构函数使用 delete[]
操作符来释放所包含的对象,所以针对的是丛台分配的数组对象。
源码
boost_1_69_0\boost\smart_ptr\scoped_array.hpp
简单使用
#include <iostream>
#include <boost/scoped_array.hpp>
using namespace std;
class A
{
public:
A() : val(0) {}
~A()
{
cout << "A destroy" << endl;
}
int val;
};
int main()
{
boost::scoped_array<A> ptr1(new A[2]);
ptr1[0].val = 1;
(ptr1.get() + 1)->val = 2;
//(ptr1.get() + 5)->val = 2; // 貌似不会报错
for (int i = 0; i < 2; i ++)
{
cout << (ptr1.get() + i)->val <<endl;
}
return 0;
}
shared_ptr
共享指针
基本与scoped_ptr 相同,不同在于不需独占一个对象,可以与其他shared_ptr 共同指向同一个对象,只有最后一个指向该对象的shared_ptr 销毁后,对象的空间才会被释放。
源码
boost_1_69_0\boost\smart_ptr\shared_ptr.hpp
简单使用
#include <iostream>
#include <boost/shared_ptr.hpp>
using namespace std;
class A
{
public:
A(const int num) : val(num) {}
~A()
{
cout << "A destroy" << endl;
}
int val;
};
int main()
{
boost::shared_ptr<A> ptr1(new A(5));
boost::shared_ptr<A> ptr2(ptr1);
cout << ptr1->val << endl;
cout << ptr2->val << endl;
ptr2.reset(new A(3));
cout << ptr1->val << endl;
cout << ptr2->val << endl;
return 0;
}
输出:
5
5
5
3
A destroy
A destroy
shared_array
共享数组
类似于共享指针。 不同在于析构时默认使用 delete[]
操作符来释放所含的对象,相当于 scoped_array 和scoped_ptr的关系
源码
shared_array.hpp
简单使用
#include <iostream>
#include <boost/shared_array.hpp>
using namespace std;
class A
{
public:
A() : val(0) {}
~A()
{
cout << "A destroy" << endl;
}
int val;
};
int main()
{
boost::shared_array<A> ptr1(new A[2]);
boost::shared_array<A> ptr2(new A[3]);
ptr1.get()->val = 1;
ptr2[0].val = 2;
ptr1.swap(ptr2);
cout << ptr1[0].val << endl;
cout << ptr2[0].val << endl;
return 0;
}
输出:
2
1
A destroy
A destroy
A destroy
A destroy
A destroy
弱指针
不能独立使用,只有配合共享指针使用才有意义
weak_ptr
必须通过 shared_ptr
来初始化的。
主要方法:lock()
作用:
返回另一个 shared_ptr,
与用于初始化弱指针的shared_ptr
共享所有权。
weak_ptr
使用场景:当函数需要一个由共享指针所管理的对象,而这个对象的生存期又不依赖于这个函数时,就可以使用弱指针。
源码
boost/weak_ptr.hpp
简单使用
#include <iostream>
#include <boost/weak_ptr.hpp>
#include <boost/shared_ptr.hpp>
using namespace std;
class A
{
public:
A(const int num) : val(num) {}
~A()
{
cout << "A destroy, num:" << val << endl;
}
int val;
};
int main()
{
boost::shared_ptr<A> ptr0(new A(1));
boost::weak_ptr<A> ptr1(ptr0);
//ptr0.reset(); boost::shared_ptr<A> ptr2 = ptr1.lock(); // 这样执行顺序不会输出ptr2->val的值
boost::shared_ptr<A> ptr2 = ptr1.lock(); ptr0.reset(); // 这样执行顺序会输出ptr2->val的值
if (ptr2)
{
cout << ptr2->val <<endl;
}
return 0;
}
以上代码,因为在ptr0释放之前,先用弱指针获得了一个共享指针,所以ptr0的reset并不会导致所指对象空间释放;要是改成注释掉的那句,那后面的ptr2->val 就不会输出。因为空间已经释放了。
介入式指针
intrusive_ptr
与shared_ptr 工作方式近似,但是共享指针自己负责记录对象的引用次数,介入式指针需要程序员自己记录。
是一个侵入式的引用计数型指针,它可以用于以下两种情形:
1、对内存占用的要求非常严格,要求必须与原始指针一样;
2、现存代码已经有了引用计数机制管理的对象
源码
intrusive_ptr.hpp
简单使用
#include <iostream>
#include <boost/intrusive_ptr.hpp>
using namespace std;
class A {
int count;
public:
A() : count(0) {}
virtual ~A()
{
cout << "A destroy" <<endl;
}
friend void intrusive_ptr_add_ref(A* p) {
++p->count;
}
friend void intrusive_ptr_release(A* p) {
if (--p->count==0)
delete p;
}
void add_ref() {
++count;
}
int release() {
return --count;
}
int getCount()
{
return count;
}
protected:
A& operator=(const A&) {
// 无操作
return *this;
}
private:
// 禁止复制构造函数
A(const A&);
};
int main(int argc, char* argv[])
{
boost::intrusive_ptr<A> ptr0(new A());
cout << ptr0->getCount() << endl;
boost::intrusive_ptr<A> ptr1(ptr0);
cout << ptr0->getCount() << endl;
return 0;
}
输出:
1
2
A destroy
指针容器
源码
boost/ptr_container/ptr_vector.hpp
简单使用
有了以上的智能指针,将对象存储到容器里,可用以下写法一:
#include <boost/shared_ptr.hpp>
#include <vector>
#include <iostream>
#include <boost/ptr_container/ptr_vector.hpp>
using namespace std;
int main()
{
// 写法一
std::vector<boost::shared_ptr<int> > v;
v.push_back(boost::shared_ptr<int>(new int(1)));
v.push_back(boost::shared_ptr<int>(new int(2)));
cout << *v[0].get() << endl;
//写法二
boost::ptr_vector<int> v1;
v1.push_back(new int(1));
v1.push_back(new int(2));
cout << *v[0] << endl;
}
第一种写法有以下问题:
1、反复声明 boost::shared_ptr
需要更多的输入
2、将 boost::shared_ptr
拷进、拷出,或者在容器内部做拷贝,需要频繁的增加或者减少内部引用计数,效率不高
Boost C++ 库提供了 指针容器 专门用来管理动态分配的对象,参考以上代码写法二。
boost::ptr_vector
专门用于动态分配的对象,它使用起来更容易也更高效。 但会独占它所包含的对象,因而容器之外的共享指针不能共享所有权,这跟 std::vector<boost::shared_ptr<int> >
相反。
专门用于管理动态分配对象的容器还包括:boost::ptr_deque
, boost::ptr_list
, boost::ptr_set
, boost::ptr_map
, boost::ptr_unordered_set
和 boost::ptr_unordered_map
。这些容器等价于C++标准里提供的那些。最后两个容器对应于std::unordered_set
和 std::unordered_map
参考:
从零开始学C++之boost库(一):详解 boost 库智能指针(scoped_ptr 、shared_ptr 、weak_ptr 源码分析) 博主总结了很多Linux C 编程的内容