Boost scoped_ptr scoped_array 以及scoped_ptr与std::auto_ptr对比
boost::scoped_ptr和std::auto_ptr非常类似,是一个简单的智能指针,它能够保证在离开作用域后对象被自动释放。下列代码演示了该指针的基本应用:
#include <string>
#include <iostream>
#include <boost/scoped_ptr.hpp> class implementation
{
public:
~implementation() { std::cout <<"destroying implementation\n"; }
void do_something() { std::cout << "did something\n"; }
}; void test()
{
boost::scoped_ptr<implementation> impl(new implementation());
impl->do_something();
} void main()
{
std::cout<<"Test Begin ... \n";
test();
std::cout<<"Test End.\n";
}
该代码的输出结果是:
|
Test Begin ... |
可以看到:当implementation类离其开impl作用域的时候,会被自动删除,这样就会避免由于忘记手动调用delete而造成内存泄漏了。
boost::scoped_ptr特点:
boost::scoped_ptr的实现和std::auto_ptr非常类似,都是利用了一个栈上的对象去管理一个堆上的对象,从而使得堆上的对象随着栈上的对象销毁时自动删除。不同的是,boost::scoped_ptr有着更严格的使用限制——不能拷贝。这就意味着:boost::scoped_ptr指针是不能转换其所有权的。
- 不能转换所有权
boost::scoped_ptr所管理的对象生命周期仅仅局限于一个区间(该指针所在的"{}"之间),无法传到区间之外,这就意味着boost::scoped_ptr对象是不能作为函数的返回值的(std::auto_ptr可以)。 - 不能共享所有权
这点和std::auto_ptr类似。这个特点一方面使得该指针简单易用。另一方面也造成了功能的薄弱——不能用于stl的容器中。 - 不能用于管理数组对象
由于boost::scoped_ptr是通过delete来删除所管理对象的,而数组对象必须通过deletep[]来删除,因此boost::scoped_ptr是不能管理数组对象的,如果要管理数组对象需要使用boost::scoped_array类。
boost::scoped_ptr的常用操作:
可以简化为如下形式:
namespace boost {
template<typename T> class scoped_ptr : noncopyable {
public:
explicit scoped_ptr(T* p = );
~scoped_ptr();
void reset(T* p = );
T& operator*() const;
T* operator->() const;
T* get() const;
void swap(scoped_ptr& b);
};
template<typename T>
void swap(scoped_ptr<T> & a, scoped_ptr<T> & b);
}
它的常用操作如下:
|
成员函数 |
功能 |
|
operator*() |
以引用的形式访问所管理的对象的成员 |
|
operator->() |
以指针的形式访问所管理的对象的成员 |
|
reset() |
释放所管理的对象,管理另外一个对象 |
|
swap(scoped_ptr& b) |
交换两个boost::scoped_ptr管理的对象 |
下列测试代码演示了这些功能函数的基本使用方法。
#include <string>
#include <iostream> #include <boost/scoped_ptr.hpp>
#include <boost/scoped_array.hpp> #include <boost/config.hpp>
#include <boost/detail/lightweight_test.hpp> void test()
{
// test scoped_ptr with a built-in type
long * lp = new long;
boost::scoped_ptr<long> sp ( lp );
BOOST_TEST( sp.get() == lp );
BOOST_TEST( lp == sp.get() );
BOOST_TEST( &*sp == lp ); *sp = 1234568901L;
BOOST_TEST( *sp == 1234568901L );
BOOST_TEST( *lp == 1234568901L ); long * lp2 = new long;
boost::scoped_ptr<long> sp2 ( lp2 ); sp.swap(sp2);
BOOST_TEST( sp.get() == lp2 );
BOOST_TEST( sp2.get() == lp ); sp.reset(NULL);
BOOST_TEST( sp.get() == NULL ); } void main()
{
test();
}
oost::scoped_ptr和std::auto_ptr的选取:
boost::scoped_ptr和std::auto_ptr的功能和操作都非常类似,如何在他们之间选取取决于是否需要转移所管理的对象的所有权(如是否需要作为函数的返回值)。如果没有这个需要的话,大可以使用boost::scoped_ptr,让编译器来进行更严格的检查,来发现一些不正确的赋值操作。
std::auto_ptr不能用在STL的container,为什么
http://bbs.csdn.net/topics/300233523
auto_ptr头文件<memory>
auto_ptr源代码:
template <typename _Tp>
class auto_ptr
{
private:
_Tp *m_ptr;
public:
typedef _Tp elementType;
// object life cycle
explicit auto_ptr(elementType *p) throw():m_ptr(p)
{
}
auto_ptr(auto_ptr &a) throw():m_ptr(a.release())
{
}
template <typename _Tp1>
auto_ptr(auto_ptr<_Tp1> &a) throw() : m_ptr(a.release())
{
}
auto_ptr& operator= (auto_ptr& a) throw()
{
reset(a.release());
return *this;
}
template <typename _Tp1>
auto_ptr& operator=(auto_ptr<_Tp1> &a) throw()
{
reset(a.release());
return *this;
}
~auto_ptr()
{
delete m_ptr;
}
// operator override
elementType& operator*() const throw()
{
assert(m_ptr != 0);
return *m_ptr;
}
elementType* operator->() const throw()
{
assert(m_ptr != 0);
return m_ptr;
}
// helper
elementType* get() const throw()
{
return m_ptr;
}
elementType* release() throw()
{
elementType *tmp = m_ptr;
m_ptr = 0;
return tmp;
}
void reset(elementType *p = 0) throw()
{
if (p != m_ptr)
{
delete m_ptr;
m_ptr = p;
}
}
};
boost::scoped_ptr源代码:
#ifndef BOOST_SMART_PTR_SCOPED_PTR_HPP_INCLUDED
#define BOOST_SMART_PTR_SCOPED_PTR_HPP_INCLUDED
#include <boost/assert.hpp>
#include <boost/checked_delete.hpp>
#include <boost/detail/workaround.hpp>
#ifndef BOOST_NO_AUTO_PTR
# include <memory> // for std::auto_ptr
#endif
namespace boost
{
// Debug hooks
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
void sp_scalar_constructor_hook(void * p);
void sp_scalar_destructor_hook(void * p);
#endif
// scoped_ptr mimics a built-in pointer except that it guarantees deletion
// of the object pointed to, either on destruction of the scoped_ptr or via
// an explicit reset(). scoped_ptr is a simple solution for simple needs;
// use shared_ptr or std::auto_ptr if your needs are more complex.
template<class T> class scoped_ptr // noncopyable
{
private:
T * px;
scoped_ptr(scoped_ptr const &);
scoped_ptr & operator=(scoped_ptr const &);
typedef scoped_ptr<T> this_type;
void operator==( scoped_ptr const& ) const;
void operator!=( scoped_ptr const& ) const;
public:
typedef T element_type;
explicit scoped_ptr( T * p = 0 ): px( p ) // never throws
{
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
boost::sp_scalar_constructor_hook( px );
#endif
}
#ifndef BOOST_NO_AUTO_PTR
explicit scoped_ptr( std::auto_ptr<T> p ): px( p.release() ) // never throws
{
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
boost::sp_scalar_constructor_hook( px );
#endif
}
#endif
~scoped_ptr() // never throws
{
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
boost::sp_scalar_destructor_hook( px );
#endif
boost::checked_delete( px );
}
void reset(T * p = 0) // never throws
{
BOOST_ASSERT( p == 0 || p != px ); // catch self-reset errors
this_type(p).swap(*this);
}
T & operator*() const // never throws
{
BOOST_ASSERT( px != 0 );
return *px;
}
T * operator->() const // never throws
{
BOOST_ASSERT( px != 0 );
return px;
}
T * get() const // never throws
{
return px;
}
// implicit conversion to "bool"
#include <boost/smart_ptr/detail/operator_bool.hpp>
void swap(scoped_ptr & b) // never throws
{
T * tmp = b.px;
b.px = px;
px = tmp;
}
};
template<class T> inline void swap(scoped_ptr<T> & a, scoped_ptr<T> & b) // never throws
{
a.swap(b);
}
// get_pointer(p) is a generic way to say p.get()
template<class T> inline T * get_pointer(scoped_ptr<T> const & p)
{
return p.get();
}
} // namespace boost
#endif // #ifndef BOOST_SMART_PTR_SCOPED_PTR_HPP_INCLUDED
分析:
二者实现原理是相同的,都是通过创建一个类的对象调用类的析构函数来释放掉类的成员,但是scoped_ptr的安全性要高(不是指内存泄漏问题),scoped_ptr将拷贝构造写进私有,这就保证了使用scoped_ptr不可以转让,否者auto_ptr造成delete两次同一块内存,错误。以后在编码中,内存泄漏问题的关于指针可以通过使用上面两个类,但是对于使用上面两种类是好是坏,还是使用delete,看情况。
//@转载请链接相应地址http://blog.sina.com.cn/s/articlelist_2684002282_0_1.html
-----------------------------------
scoped_array
scoped_array使用起来很方便,轻巧,而且速度和原始指针相差无几. 而且更加安全..
scoped_array主要有以下几个特点;
1.构造函数接受的的指针必须是new[]返回的结果,而不能是new返回的结果.
2.没有*、->操作符的重载,因为scoped_array管理的不是一个普通的指针.
3.析构函数使用delete[]释放内存而不是用delete;
4.提供operator[]操作符,,因此我们可以像普通数组一样操作他,
5.没有begin\end类似于容器的迭代器操作函数.
#include <string>
#include <iostream>
#include<boost/scoped_array.hpp> #define MAX 10
using namespace std; int main()
{
boost::scoped_array<char> ptr;
ptr.reset(new char[MAX]); for(int i=;i<MAX;i++)
{
ptr[i]='a'+i;
cout<<ptr[i]<<endl;
}
}
需要动态分配数组时,通常最好用std::vector来实现,但是有两种情形看起来用数组更适合: 一种是为了优化,用vector多少有一些额外的内存和速度开销;另一种是为了某种原因,要求数组的大小必须是固定的。动态分配的数组会遇到与普通指针一样的危险,并且还多了一个(也是最常见的一个),那就是错误调用delete操作符而不是delete[]操作符来释放数组。我曾经在你想象不到的地方见到过这个错误,那也是它常被用到的地方,就是在你自己实现的容器类里!scoped_array 为数组做了scoped_ptr为单个对象指针所做的事情:它负责释放内存。区别只在于scoped_array 是用delete[] 操作符来做这件事的。
scoped_array是一个单独的类而不是scoped_ptr的一个特化,其原因是,因为不可能用元编程技术来区分指向单个对象的指针和指向数组的指针。不管如何努力,也没有人能发现一种可靠的方法,因为数组太容易退化为指针了,这使得没有类型信息可以表示它们是指向数组的。结果,只能由你来负责,使用scoped_array而不是scoped_ptr,就如你必须用delete[]操作符而不是用delete操作符一样。这样的好处是scoped_array 负责为你处理释放内存的事情,而你则告诉scoped_array 我们要处理的是数组,而不是裸指针。
scoped_array与scoped_ptr非常相似,不同的是它提供了operator[] 来模仿一个裸数组。
scoped_array 是比普通的动态分配数组更好用。它处理了动态分配数组的生存期管理问题,就如scoped_ptr管理对象指针的生存期一样。但是记住,多数情况下应该使用std::vector,它更灵活、更强大。只有当你需要确保数组的大小是固定的时候,才使用scoped_array 来替代 std::vector.
使用建议:
scoped_array使用起来很轻便,没有为程序增加额外的负担,它的速度与原始数组一样快,很适合习惯用new操作符在堆上分配内在的同仁,但scoped_array功能有限,不能动态增长,也没有迭代支持,不能搭配STL算法,仅有一个纯粹的数组接口。
需要动态数组的话尽量使用std::vector容器,相比之下它比scoped_array更灵活,而只付出了很小的代价。
- vector<int> sa(100,2);
- sa[30] = sa[10] + sa[20];
很显然,std::vector更简洁,而且有丰富的成员函数来操作数据,易于维护。
除非对性能有非常苛刻的要求,或者编译器不支持标准库(比如某些嵌入式操作系统),否则不推荐使用scoped_array,它只是为了与老式的C风格代码兼容而使用的类,它的出现往往代表你的代码中存在隐患。
auto_ptr实现:
Boost scoped_ptr scoped_array 以及scoped_ptr与std::auto_ptr对比的更多相关文章
- 智能指针剖析(上)std::auto_ptr与boost::scoped_ptr
1. 引入 C++语言中的动态内存分配没有自动回收机制,动态开辟的空间需要用户自己来维护,在出函数作用域或者程序正常退出前必须释放掉. 即程序员每次 new 出来的内存都要手动 delete,否则会造 ...
- C++智能指针剖析(上)std::auto_ptr与boost::scoped_ptr
1. 引入 C++语言中的动态内存分配没有自动回收机制,动态开辟的空间需要用户自己来维护,在出函数作用域或者程序正常退出前必须释放掉. 即程序员每次 new 出来的内存都要手动 delete,否则会造 ...
- std::auto_ptr
auto_ptr是C++标准库中(<utility>)为了解决资源泄漏的问题提供的一个智能指针类模板(注意:这只是一种简单的智能指针) auto_ptr的实现原理其实就是RAII,在构造的 ...
- C++安全异常std:auto_ptr
auto_ptr它是C++标准库(<utility>)为了一个智能指针类模板来解决资源泄漏所提供的问题(注意:这只是一个简单的智能指针) auto_ptr在事实原则的实现RAII,对资源的 ...
- [3] 智能指针std::auto_ptr
[1]std::auto_ptr 对于编译器来说,智能指针实质是一个栈对象,而并非指针类型. 智能指针通过构造函数获取堆内存的管理所有权,而在其生命期结束时,再通过析构函数释放由它所管理的堆内存. 所 ...
- 关于std:auto_ptr std:shared_ptr std:unique_ptr
很多人听说过标准auto_ptr智能指针机制,但并不是每个人都天天使用它.这真是个遗憾,因为auto_ptr优雅地解决了C++设计和编码中常见的问题,正确地使用它可以生成健壮的代码.本文阐述了如何正确 ...
- 「caffe编译bug」 undefined reference to `boost::match_results<__gnu_cxx::__normal_iterator<char const*, std::__cxx11
CXX/LD -o .build_release/tools/test_net.binCXX/LD -o .build_release/tools/convert_annoset.binCXX/LD ...
- boost准模板库scoped_ptr指针的使用以及auto_ptr智能指针的对照
首先我们看看scoped_ptr的基本使用,包括了swap(),get(),reset()的使用,重要的提醒是作用域结束的时候会自己主动析构,无需手动的释放资源: #include<boost/ ...
- C++ 智能指针 std::auto_ptr 分析
背景介绍: RAll机制 定义一个类来封装资源的分配和释放,在构造函数中完成资源的分配和初始化,在析构函数中完成资源的清理,从而保证资源的正确初始化和清理 ps:智能指针就是RAll机制的一种应用,智 ...
随机推荐
- hdu6060 RXD and dividing 贪心
/** 题目:hdu6060 RXD and dividing 链接:http://acm.hdu.edu.cn/showproblem.php?pid=6060 题意:贪心 给定一颗树,n个节点,编 ...
- jQuery学习笔记1——操作属性
一.获得和设置内容 三个简单实用的用于 DOM 操作的 jQuery 方法: text() - 设置或返回所选元素的文本内容, 得到匹配元素集合中每个元素的文本内容结合,包括他们的后代, 即由所有匹配 ...
- 2017 ACM区域赛(西安) 参赛流水账
day 0: 周五, 鸽了概统课,早上和紫金港的几位小伙伴一起打车去萧山机场,从咸阳机场到西北工业大学坐了五十多个站的公交车,感觉身体被掏空.晚上在宾馆本来打算补之前训练的一个题,想想还是先花个十来分 ...
- 使用StringTokenizer分解字符串
Java切割字符串.一般使用substring.split.StringTokenizer来处理,前两种是String对象的方法,使用字符串能够直接处理,本文介绍下StringTokenizer的使用 ...
- 修改原型给数组对象添加forEach
Array.prototype.forEach = function (callback, context) { for (var i = 0; i < this.length; i++) { ...
- 【PyQt】插入排序算法
# coding=utf-8 import sys from PyQt4.QtGui import * from PyQt4.QtCore import * class MainWindow(QMai ...
- Android中的Manifest.permission(应用权限)整理
ACCESS_CHECKIN_PROPERTIES 允许读/写登记数据库(checkin database),中的“properties”表,用来改变他的值来上传东西. 这个权限第三方应用无法使用. ...
- php 对字符串的分块处理
//如何把以下的字符串分成每一个小块, 如:2017.2.14\n我们都是中国人\n小日本 这样的为一个小块 $str = '2017.2.14 我们都是中国人 小日本 2017.2.15 订单取消 ...
- 并发容器J.U.C --组件FutureTask、ForkJoin、BlockingQueue
FutureTask FutureTask是J.U.C中的类,是一个可删除的异步计算类.这个类提供了Future接口的的基本实现,使用相关方法启动和取消计算,查询计算是否完成,并检索计算结果.只有在计 ...
- STL中的排序算法
本文转自:STL中的排序算法 1. 所有STL sort算法函数的名字列表: 函数名 功能描述 sort 对给定区间所有元素进行排序 stable_sort 对给定区间所有元素进行稳定排序 ...