scoped_array源码剖析
2017-01-20 19:38
507 查看
scoped_array很想scoped_ptr,它包装了new[]操作符(不是单纯的new)在堆上分配的动态数组,为动态数组提供了一个代理,保证可以正确的释放内存。
上面的源码和我之前分析过的scoped_ptr类似,只不过变成了对数组的封装。scoped_array析构函数中的check_delete实现是这样的:
呵呵,这里是delete[] x。
构造函数接受的指针p必须是new[]的结果,而不能是new表达式的结果。
没有*、->操作符重载,因为scoped_array持有的不是一个普通指针。
析构函数使用delete []释放资源,而不是delete。
提供operator[]操作符重载,可以像普通数组一样用下标访问元素。
没有begin()、end()等类似容器的迭代器操作函数
代码示例:
scoped_array重载了operator[],因此用起来就像是一个普通的数组,但不能使用”首地址+N”的方式访问元素,并且scoped_array不提供数组索引的范围检查,如果使用超过动态数组大小的索引或者是负数索引将引发未定义行为。
参考:
Boost程序库完全开发指南,作者:罗剑锋
源码剖析
scoped_array的源码如下:namespace boost { // scoped_array extends scoped_ptr to arrays. Deletion of the array pointed to // is guaranteed, either on destruction of the scoped_array or via an explicit // reset(). Use shared_array or std::vector if your needs are more complex. template<class T> class scoped_array // noncopyable { private: T * px; scoped_array(scoped_array const &); scoped_array & operator=(scoped_array const &); typedef scoped_array<T> this_type; void operator==( scoped_array const& ) const; void operator!=( scoped_array const& ) const; public: typedef T element_type; explicit scoped_array( T * p = 0 ) BOOST_NOEXCEPT : px( p ) { } ~scoped_array() // never throws { boost::checked_array_delete( px ); } void reset(T * p = 0) // never throws (but has a BOOST_ASSERT in it, so not marked with BOOST_NOEXCEPT) { BOOST_ASSERT( p == 0 || p != px ); // catch self-reset errors this_type(p).swap(*this); } //重载了operator[]模拟数组,但不支持*(p+i)这种访问方式 T & operator[](std::ptrdiff_t i) const // never throws (but has a BOOST_ASSERT in it, so not marked with BOOST_NOEXCEPT) { BOOST_ASSERT( px != 0 ); BOOST_ASSERT( i >= 0 ); return px[i]; } T * get() const BOOST_NOEXCEPT { return px; } // implicit conversion to "bool" #include <boost/smart_ptr/detail/operator_bool.hpp> void swap(scoped_array & b) BOOST_NOEXCEPT { T * tmp = b.px; b.px = px; px = tmp; } }; template<class T> inline void swap(scoped_array<T> & a, scoped_array<T> & b) BOOST_NOEXCEPT { a.swap(b); } } // namespace boost
上面的源码和我之前分析过的scoped_ptr类似,只不过变成了对数组的封装。scoped_array析构函数中的check_delete实现是这样的:
template<class T> inline void checked_array_delete(T * x) { typedef char type_must_be_complete[ sizeof(T)? 1: -1 ]; (void) sizeof(type_must_be_complete); delete [] x; }
呵呵,这里是delete[] x。
特点
scoped_array的主要特点如下:构造函数接受的指针p必须是new[]的结果,而不能是new表达式的结果。
没有*、->操作符重载,因为scoped_array持有的不是一个普通指针。
析构函数使用delete []释放资源,而不是delete。
提供operator[]操作符重载,可以像普通数组一样用下标访问元素。
没有begin()、end()等类似容器的迭代器操作函数
用法
sceopd_array与scoped_ptr源于相同的设计思想,故而用法非常相似:它只能在被生命的作用域内使用,不能拷贝、赋值。唯一不同的是scoped_array包装的是new[]产生的指针,并在析构时调用delete[],因为它管理的是动态数组,而不是单个对象。代码示例:
class test { public: test() { cout<<"ctor"<<endl; } ~test() { cout<<"dtor"<<endl; } }; int main() { int *arr = new int[100]; scoped_array<int> sa(arr); std::fill_n(&sa[0], 100, 5); sa[10] = sa[20] + sa[30]; cout<<sa[10]<<endl; scoped_array<test> ptest(new test[3]); return 0; }
scoped_array重载了operator[],因此用起来就像是一个普通的数组,但不能使用”首地址+N”的方式访问元素,并且scoped_array不提供数组索引的范围检查,如果使用超过动态数组大小的索引或者是负数索引将引发未定义行为。
使用建议
scoped_array没有给程序增加额外的负担,它的速度与原始数组同样快。但scoped_array功能很有限,不能动态增长。也没有迭代器支持,不能搭配STL算法,仅有一个纯粹的”裸”数组接口。而且我们要尽量避免使用new[]操作符,尽量使用scoped_array,甚至是更好的std::vector。参考:
Boost程序库完全开发指南,作者:罗剑锋
相关文章推荐
- 从源码安装Mysql/Percona 5.5
- share_ptr的几个注意点
- boost相关小知识(长期顶置更新)
- 浅析Ruby的源代码布局及其编程风格
- jQuery 判断是否包含在数组中Array[]的方法
- 解析从源码分析常见的基于Array的数据结构动态扩容机制的详解
- 关于c++ 智能指针及 循环引用的问题
- 浅析C++中boost.variant的几种访问方法
- asp.net 抓取网页源码三种实现方法
- javascript数组操作总结和属性、方法介绍
- mysql_fetch_assoc和mysql_fetch_row的功能加起来就是mysql_fetch_array
- JavaScript Array扩展实现代码
- JavaScript:Array类型全面解析
- JavaScript之数组(Array)详解
- Javascript实现Array和String互转换的方法
- C#中Array与ArrayList用法及转换的方法
- Array栈方法和队列方法的特点说明
- Array.prototype.slice 使用扩展
- Array, Array Constructor, for in loop, typeof, instanceOf
- 实例详解ECMAScript5中新增的Array方法