导语
智能指针的原理基于RAII机制:资源申请即初始化。智能指针确保在任何情况下,动态分配的内存都能得到正确释放,避免程序因内存不足等原因造成的崩溃出现,即使程序因为异常中断也不必担心。
用一个动态分配的对象的地址初始化智能指针。 智能指针确保资源离开作用域后会被自动释放。
//简单理解RAII机制
class myClass
{
myClass() { myBuf = new int[1024]; }
~myClass() {
if(nullptr != myBuf) {
delete myBuf;
myBuf = nullptr;
}
}
void usePointer() { //usePointer }
private:
int* myBuf;
};
boost提供的智能指针包括如下,除如下所示的头文件,也可以使用<boost/smart_ptr.hpp>包含所有用到的智能指针。
智能指针类型 说明 所在头文件 boost::scope_ptr 作用域指针,独占一个动态分配的对象 <boost/scoped_ptr.hpp> boost::scoped_array 作用域数组,是否用方式类似作用域指针,不同在于作用域数组必须通过动态分配的数组来初始化初始化 <boost/scoped_array.hpp> boost::shared_ptr 共享指针,同std::shared_ptr,基本类似作用域指针,与作用域指针不同在于不一定要独占一个对象 <boost/shared_ptr.hpp> boost::shared_array 共享数组,类似共享指针,不同共享数组必须通过动态分配的数组的地址来初始化。 <<boost>shared_array.hpp> boost::weak_ptr 弱指针,配合共享指针一起使用 <boost/weak_ptr.hpp> boost::intrusive_ptr 介入式指针,同共享指针,但需要程序员记录引用某个对象的共享指针的数量 <boost/intrusive_ptr.hpp> boost::ptr_vector 指针容器,管理动态分类的对象 <boost/ptr_container/ptr_vector.hpp>
1、作用域指针–boost::scoped_ptr
类boost::scoped_ptr定义在<boost/scoped_ptr.hpp>中。
一个作用域指针独占一个动态分配的对象,对应的类名是boost::scoped_ptr。
作用域指针不能传递它包含的对象的所有权到另一个作用域指针。
在不需要所有权传递的时候应该优先使用boost::scoped_ptr。
可以通过类似于普通指针的接口来访问boost::scoped_ptr的对象。
boost::scoped_ptr的成员函数有:
- 重载操作符:operator*()、operator->、operator bool();
- 返回对象的地址:get();
- 重新初始化智能指针:reset(),该函数会先释放所包含的对象,然后使用新创建的对象复制。
boost::scoped_ptr的析构函数使用delete操作符释放所包含的对象,所以不能用动态分配的数组来初始化,可以使用作用域指针boost::scoped_array类。
2、作用域数组–boost::scoped_array
类boost::scoped_array定义在<boost/scoped_array.hpp>中。
使用方式与作用域指针相似,不同点在于作用域数组的析构函数使用delete[]操作符释放包含的对象,所以boost::scoped_array对象必须通过动态分配的数组来初始化。
boost::scoped_array的常用成员函数有:
- 重载操作符:operator[]()、operator bool(),所以可以通过operator[]访问数组中特定的元素;
- 返回对象的地址:get();
- 重新初始化智能指针:reset(),该函数会先释放所包含的对象,然后使用新创建的对象复制。
类boost::shared_ptr定义在<boost/shared_ptr>中。
boost::shared_ptr与memory中定义的std::shared_ptr类似。
boost::shared_ptr基本类似boost::scoped_ptr,不同点在于boost::shared_ptr不一定要独占一个对象,可以和其它boost:;shared_ptr类型的智能指针共享所有权。共享所有权后,当引用对象的最后一个智能指针销毁后,对象才会被释放。
所有权可以在boost::shared_ptr之间共享,任何一个共享指针都可以复制,这样就可以在标准容器里存储智能指针,而std::auto_ptr不能存储在标准容器钟,因为在std::auto_ptr在拷贝的时候传递了所有权。
boost::shared_ptr常用的成员函数有:
- 重载操作符:operator*()、operator->()、operator bool();
- 获取和初始化所包含对象的地址的函数:get()和reset();
默认情况下boost::shared_ptr使用delete销毁所含的对象,可以在构造函数的第二个参数指定用什么方式销毁所含的对象。
示例:
boost::shared_ptr<void> hins(OpenProcess(PROCESS_SET_INFORMATION,FALSE,GetCurrentProcessId()),CloseHandle);
SetPriorityClass(hins.get(),HIGH_PRIORITY_CLASS);
构造函数的第二个参数是 Windows API 函数 CloseHandle()。 当变量 hins 超出它的作用域时,调用CloseHandle()来销毁所含的对象。 为了避免编译错误,该函数只能带一个 HANDLE 类型的参数, CloseHandle() 正好符合要求,CloseHandle()会在共享指针超出它的作用域时自动调用。
类boost::shared_array定义在<boost/shared_array>中
共享数组的行为类似于共享指针,不同点在于共享数组析构时,默认使用delete[]操作符释放包含的对象。所以共享数组必须通过动态分配的数组的地址来初始化。
boost::shared_array提供的成员函数有:
- 重载运算符:operator[]()、operator bool();
- 获取和初始化所包含对象的地址的函数:get()和reset();
5、弱指针–boost::weak_ptr
类boost::weak_ptr定义在<boost/weak_ptr.hpp>中
弱指针需要配合共享指针一起使用。当一个函数需要一个由共享指针所管理的对象,而这个对象的生存期又不依赖于这个函数时,就可以使用弱指针。只要程序中还有一个共享指针掌管着这个对象,函数就可以使用该对象。 如果共享指针复位了,就算函数里能得到一个共享指针,对象也不存在了。
boost::weak_ptr通过boost::shared_ptr来初始化,初始化之后基本上只提供一个有用的方法:lock(),lock()的返回boost::shared_ptr与用来初始化弱指针的共享指针共享所有权。
6、介入式指针–boost::intrusive_ptr
类boost::intrusive_ptr定义在<boost/intrusive_ptr.hpp>中
介入式指针的工作方式和共享指针完全一样。不同在于,对介入式指针来说,程序员就得自己来做记录。 对于框架对象来说这就特别有用,因为它们记录着自身被引用的次数。
boost::ptr_vector 类的定义在 <boost/ptr_container/ptr_vector.hpp> 中
多数情况下,智能指针对象要存储在容器中。
然而现实是反复声明boost::shared_ptr需要更多的输入,另外boost::shared_ptr拷进、拷出,或者在容器内部做拷贝需要频繁的增加或减少内部引用计数,导致效率不高,boost C++库提供指针容器专门管理动态分配的对象。
boost::ptr_vector独占它所包含的对象,因而容器之外的共享指针不能共享所有权,这跟std::vector<boost::shared_ptr<int> >相反。
除了boost::ptr_vector之外,专门用于管理动态分配对象的容器还包括:
- boost::ptr_deque
- boost::ptr_list
- boost::ptr_set
- boost::ptr_map
- boost::ptr_unordered_set
- boost::ptr_unordered_map
使用示例参考:
const int g_width = 8000;
const int g_height = 6000;
struct MyStruct
{
float fR[g_width*g_height / 4];
float fGR[g_width*g_height / 4];
float fGB[g_width*g_height / 4];
float fB[g_width*g_height / 4];
}LSCMat;
void test_smart_pointers(){
// 作用域指针 数组
{
MyStruct *p = NULL;
boost::scoped_ptr<MyStruct> scopedptr(new MyStruct);
p = scopedptr.get();
//boost::scoped_ptr<MyStruct> scopedptr_other(scopedptr); // 该语句错误,作用域指针不能共享所有权
//scopedptr_other = scopedptr; // 该语句错误
scopedptr.reset(new MyStruct);
p = scopedptr.get();
boost::scoped_array<int> scoArray(new int[g_width*g_height]);
int* pbuf = scoArray.get();
printf("\nscoArray = 0x%x,\tpbuf = 0x%x,\tpbuf[0] = %d", scoArray, pbuf, pbuf[0]);
memset(pbuf, 255, g_width*g_height*sizeof(int));
scoArray.reset(new int[g_width]);
//printf("\nscoArray = 0x%x,\tpbuf = 0x%x,\tpbuf[0] = %d", scoArray, pbuf, pbuf[0]); // 错误,pbuf已经被释放,不能再访问pbuf[0]
printf("\nscoArray = 0x%x,\tpbuf = 0x%x", scoArray, pbuf);
}
// 共享指针、数组
{
boost::shared_ptr<MyStruct> shareptr(new MyStruct);
boost::shared_ptr<MyStruct> shareptr_other(shareptr);
shareptr_other.get()->fR[0] = 3.14;
printf("\nshareptr = 0x%x,\tshareptr_other = 0x%x,\tshareptr.get()->fR[0] = %g", shareptr, shareptr_other, shareptr.get()->fR[0]);
boost::shared_array<float> sharArray(new float[g_width*g_height]);
boost::shared_array<float> sharArr_other(sharArray);
boost::shared_array<float> other1(sharArray);
boost::shared_array<float> other2(sharArray);
boost::shared_array<float> other3(sharArray);
printf("\nshareptr = 0x%x, \nother = 0x%x,\nother1 = 0x%x, \nother2 = 0x%x, \nother3 = 0x%x", sharArray, sharArr_other, other1, other2, other3);
float *p = sharArray.get();
p[0] = 3.14;
printf("\nsharArray = 0x%x,\tsharArr_other = 0x%x,\tsharArr_other[0] = %g", sharArray, sharArr_other, sharArr_other[0]);
}
// 指针容器
{
boost::ptr_vector<int> v;
v.push_back(new int(1));
v.push_back(new int(2));
int p = v.at(0);
printf("p = %d", p);
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/46148.html