boost教程之智能指针

智能指针的原理基于一个常见的习语叫做 RAII :资源申请即初始化。智能指针确保在任何情况下,动态分配的内存都能得到正确释放,从而将开发人员从这项任务中解放了出来。 这包括程序因为异常而中断,原本用于释放内存的代码被跳过的场景。

1、C++标准库中的智能指针

1998年修订的第一版C++标准只提供了一种智能指针: std::auto_ptr包含在头文件<memory>中:

    用法一:  
    std::auto_ptr<MyClass>m_example(new MyClass());  
      
    用法二:  
    std::auto_ptr<MyClass>m_example;  
    m_example.reset(new MyClass());  
      
    用法三(指针的赋值操作):  
    std::auto_ptr<MyClass>m_example1(new MyClass());  
    std::auto_ptr<MyClass>m_example2(new MyClass());  
    m_example2=m_example1;  

std::auto_ptr 有三个常用的成员函数,分别是:

  1. get():获取智能指针的首地址
  2. reset():重置智能指针的内存位置,并将原内存置NULL
  3. release():释放内存

在使用std::auto_ptr时要注意一个陷阱,那就是指针的托管权是会转移的。例如:

auto_ptr<int> pI1(new int);  
auto_ptr<int> pI2=pI1;
/*
此时,pI2将拥有该指针,而pI1没有了,如果再用pI1去引用,必然导致内存错误。
*/

2、作用域指针(boost::scoped_ptr)及作用域数组(boost:scoped_array)

(1)作用域指针(boost::scoped_ptr)

一个作用域指针独占一个动态分配的对象,即不允许通过赋值操作使两个作用域指针指定同一块地址,所以也不存在指向对象的所有权转移的情况。它的定义在 boost/scoped_ptr.hpp 中。只包含两个成员函数,分别是get()及reset()。boost::scoped_ptr 的析构函数中使用 delete 操作符来释放所包含的对象,所以它不能用动态分配的数组来做初始化,因为这需要调用 delete[] 来释放。

(2)作用域数组(boost:scoped_array)

作用域数组的使用方式与作用域指针相似。 关键不同在于,作用域数组的析构函数使用 delete[] 操作符来释放所包含的对象。 因为该操作符只能用于数组对象,所以作用域数组必须通过动态分配的数组来初始化。

对应的作用域数组类名为 boost::scoped_array,它的定义在 boost/scoped_array.hpp 里。

因为其重载了操作符 operator[]()operator bool()。 可以通过 operator[]() 操作符访问数组中特定的元素。例如:

#include <boost/scoped_array.hpp> 

int main() 
{ 
  boost::scoped_array<int> i(new int[2]); 
  *i.get() = 1; 
  i[1] = 2; 
  i.reset(new int[3]); 
} 

3、共享指针(boost::shared_ptr)及共享数组(boost::shared_array)

(1)共享指针(boost::shared_ptr)

这是使用率最高的智能指针。 它已经作为技术报告1(TR 1)的一部分被添加到标准里了。 如果开发环境支持的话,可以使用 <memory> 中定义的 std::shared_ptr。 在 Boost C++ 库里,这个智能指针命名为 boost::shared_ptr,定义在 boost/shared_ptr.hpp 里。只包含两个成员函数,分别是get()及reset()。

boost::shared_ptr 基本上类似于 boost::scoped_ptr。 关键不同之处在于 boost::shared_ptr没有独占一个对象。 它可以和其他 boost::shared_ptr 类型的智能指针共享所有权,即可以进行指针间的赋值操作。 且只有当引用对象的最后一个智能指针被销毁后,对象才会被释放,即所有权可以在 boost::shared_ptr 之间共享。所以,我们可以放心的在标准容器里存储boost::shared_ptr指针了。

默认情况下,boost::shared_ptr 使用 delete 操作符来销毁所含的对象。 然而,具体通过什么方法来销毁,是可以指定的,boost::shared_ptr 的构造函数的第二个参数是一个普通函数或者函数对象,该参数用来销毁所含的对象。就像下面的例子里所展示的:

#include <boost/shared_ptr.hpp> 
#include <iostream>
void MyFree(int* p)
{
	delete p;
	std::cout<<"执行我自定义的释放函数"<<std::endl;
}

int main()
{
	{
		boost::shared_ptr<int>i(new int(10), MyFree);
	}

	system("pause");
}

(2)共享数组(boost::shared_array)

共享数组的行为类似于共享指针。 关键不同在于共享数组在析构时,默认使用 delete[] 操作符来释放所含的对象。 因为这个操作符只能用于数组对象,共享数组必须通过动态分配的数组的地址来初始化。就像共享指针那样,所含对象的所有权可以跟其他共享数组来共享。

共享数组对应的类型是 boost::shared_array,它的定义在 boost/shared_array.hpp 里。

4、弱指针(boost::weak_ptr)

弱指针只有在配合共享指针一起使用时才有意义。 弱指针 boost::weak_ptr 的定义在 boost/weak_ptr.hpp 里。

boost::weak_ptr 必定总是通过 boost::shared_ptr 来初始化的。一旦初始化之后,它基本上只提供一个有用的方法: lock()。此方法返回的该弱指针初始化时所传入的共享指针,共享其所有权。 如果这个共享指针没有初始化,返回的共享指针也将是NULL。弱指针本身对于对象的生存期没有任何影响.

当函数需要一个由共享指针所管理的对象,而这个对象的生存期又不依赖于这个函数时,就可以使用弱指针。 通过弱指针获取共享指针后,在其他位置使其引用次数加1,这样该内存就不会因为生命周期结束而释放了。但如果共享指针reset()复位了,之前得到的共享指针也将被释放。

5、指针容器

Boost C++ 库提供了  指针容器 专门用来管理动态分配的对象。

#include <boost/ptr_container/ptr_vector.hpp> 

int main() 
{ 
  boost::ptr_vector<int> v; 
  v.push_back(new int(1)); 
  v.push_back(new int(2)); 
} 

boost::ptr_vector 类的定义在 boost/ptr_container/ptr_vector.hpp 里,它跟前一个例子中用 boost::shared_ptr 模板参数来初始化的容器具有相同的工作方式。 boost::ptr_vector 专门用于动态分配的对象,它使用起来更容易也更高效。 boost::ptr_vector 独占它所包含的对象,因而容器之外的共享指针不能共享所有权,这跟 std::vector<boost::shared_ptr<int> > 相反。

除了 boost::ptr_vector 之外,专门用于管理动态分配对象的容器还包括:boost::ptr_dequeboost::ptr_listboost::ptr_setboost::ptr_mapboost::ptr_unordered_setboost::ptr_unordered_map。这些容器等价于C++标准里提供的那些。最后两个容器对应于std::unordered_setstd::unordered_map,它们作为技术报告1的一部分加入 C++ 标准。 如果所使用的 C++ 标准实现不支持技术报告1的话,还可以使用 Boost C++ 库里实现的 boost::unordered_setboost::unordered_map

6、介入式指针( boost::intrusive_ptr

大体上,介入式指针的工作方式和共享指针完全一样。 boost::shared_ptr 在内部记录着引用到某个对象的共享指针的数量,可是对介入式指针来说,程序员就得自己来做记录。 对于框架对象来说这就特别有用,因为它们记录着自身被引用的次数。

介入式指针 boost::intrusive_ptr 定义在 boost/intrusive_ptr.hpp 里。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Chiang木

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值