- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章浅析Boost智能指针:scoped_ptr shared_ptr weak_ptr由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
一. scoped_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"; } 。
该代码的输出结果是:
可以看到:当implementation类离其开impl作用域的时候,会被自动删除,这样就会避免由于忘记手动调用delete而造成内存泄漏了.
。
boost::scoped_ptr特点: boost::scoped_ptr的实现和std::auto_ptr非常类似,都是利用了一个栈上的对象去管理一个堆上的对象,从而使得堆上的对象随着栈上的对象销毁时自动删除。不同的是,boost::scoped_ptr有着更严格的使用限制——不能拷贝。这就意味着:boost::scoped_ptr指针是不能转换其所有权的.
1.不能转换所有权 boost::scoped_ptr所管理的对象生命周期仅仅局限于一个区间(该指针所在的"{}"之间),无法传到区间之外,这就意味着boost::scoped_ptr对象是不能作为函数的返回值的(std::auto_ptr可以).
2.不能共享所有权 这点和std::auto_ptr类似。这个特点一方面使得该指针简单易用。另一方面也造成了功能的薄弱——不能用于stl的容器中.
3.不能用于管理数组对象 由于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 = 0); ~scoped_ptr(),
void reset(T* p = 0),
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->() 。 |
以指针的形式访问所管理的对象的成员 。 |
get() 。 |
释放所管理的对象,管理另外一个对象 。 |
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(); } 。
boost::scoped_ptr和std::auto_ptr的选取: boost::scoped_ptr和std::auto_ptr的功能和操作都非常类似,如何在他们之间选取取决于是否需要转移所管理的对象的所有权(如是否需要作为函数的返回值)。如果没有这个需要的话,大可以使用boost::scoped_ptr,让编译器来进行更严格的检查,来发现一些不正确的赋值操作.
。
二. shared_ptr boost::scoped_ptr虽然简单易用,但它不能共享所有权的特性却大大限制了其使用范围,而boost::shared_ptr可以解决这一局限。顾名思义,boost::shared_ptr是可以共享所有权的智能指针,首先让我们通过一个例子看看它的基本用法:
#include <string> #include <iostream> #include <boost/shared_ptr.hpp> 。
。
class implementation { public: ~implementation() { std::cout <<"destroying implementation\n"; } void do_something() { std::cout << "did something\n"; } },
void test() { boost::shared_ptr<implementation> sp1(new implementation()); std::cout<<"The Sample now has "<<sp1.use_count()<<" references\n",
boost::shared_ptr<implementation> sp2 = sp1; std::cout<<"The Sample now has "<<sp2.use_count()<<" references\n"; sp1.reset(); std::cout<<"After Reset sp1. The Sample now has "<<sp2.use_count()<<" references\n",
sp2.reset(); std::cout<<"After Reset sp2.\n"; } 。
void main() { test(); } 。
该程序的输出结果如下:
可以看到,boost::shared_ptr指针sp1和sp2同时拥有了implementation对象的访问权限,且当sp1和sp2都释放对该对象的所有权时,其所管理的的对象的内存才被自动释放。在共享对象的访问权限同时,也实现了其内存的自动管理.
。
boost::shared_ptr的内存管理机制: boost::shared_ptr的管理机制其实并不复杂,就是对所管理的对象进行了引用计数,当新增一个boost::shared_ptr对该对象进行管理时,就将该对象的引用计数加一;减少一个boost::shared_ptr对该对象进行管理时,就将该对象的引用计数减一,如果该对象的引用计数为0的时候,说明没有任何指针对其管理,才调用delete释放其所占的内存.
上面的那个例子可以的图示如下:
1.sp1对implementation对象进行管理,其引用计数为1 。
2.增加sp2对implementation对象进行管理,其引用计数增加为2 。
3.sp1释放对implementation对象进行管理,其引用计数变为1 。
4.sp2释放对implementation对象进行管理,其引用计数变为0,该对象被自动删除 。
boost::shared_ptr的特点: 和前面介绍的boost::scoped_ptr相比,boost::shared_ptr可以共享对象的所有权,因此其使用范围基本上没有什么限制(还是有一些需要遵循的使用规则,下文中介绍),自然也可以使用在stl的容器中。另外它还是线程安全的,这点在多线程程序中也非常重要.
boost::shared_ptr的使用规则: boost::shared_ptr并不是绝对安全,下面几条规则能使我们更加安全的使用boost::shared_ptr:
1.避免对shared_ptr所管理的对象的直接内存管理操作,以免造成该对象的重释放 2.shared_ptr并不能对循环引用的对象内存自动管理(这点是其它各种引用计数管理内存方式的通病)。 3.不要构造一个临时的shared_ptr作为函数的参数.
如下列代码则可能导致内存泄漏:
三. weak_ptr 。
。
循环引用: 引用计数是一种便利的内存管理机制,但它有一个很大的缺点,那就是不能管理循环引用的对象。一个简单的例子如下:
#include <string> #include <iostream> #include <boost/shared_ptr.hpp> #include <boost/weak_ptr.hpp> 。
。
class parent; class children,
typedef boost::shared_ptr<parent> parent_ptr; typedef boost::shared_ptr<children> children_ptr,
class parent { public: ~parent() { std::cout <<"destroying parent\n"; } 。
public: children_ptr children; },
class children { public: ~children() { std::cout <<"destroying children\n"; } 。
public: parent_ptr parent; },
void test() { parent_ptr father(new parent()); children_ptr son(new children),
father->children = son; son->parent = father; } 。
void main() { std::cout<<"begin test...\n"; test(); std::cout<<"end test.\n"; } 。
运行该程序可以看到,即使退出了test函数后,由于parent和children对象互相引用,它们的引用计数都是1,不能自动释放,并且此时这两个对象再无法访问到。这就引起了c++中那臭名昭著的内存泄漏.
。
一般来讲,解除这种循环引用有下面有三种可行的方法: 1.当只剩下最后一个引用的时候需要手动打破循环引用释放对象。 2.当parent的生存期超过children的生存期的时候,children改为使用一个普通指针指向parent。 3.使用弱引用的智能指针打破这种循环引用.
虽然这三种方法都可行,但方法1和方法2都需要程序员手动控制,麻烦且容易出错。这里主要介绍一下第三种方法和boost中的弱引用的智能指针boost::weak_ptr.
强引用和弱引用 一个强引用当被引用的对象活着的话,这个引用也存在(就是说,当至少有一个强引用,那么这个对象就不能被释放)。boost::share_ptr就是强引用.
相对而言,弱引用当引用的对象活着的时候不一定存在。仅仅是当它存在的时候的一个引用。弱引用并不修改该对象的引用计数,这意味这弱引用它并不对对象的内存进行管理,在功能上类似于普通指针,然而一个比较大的区别是,弱引用能检测到所管理的对象是否已经被释放,从而避免访问非法内存.
boost::weak_ptr 。
。
boost::weak_ptr<T>是boost提供的一个弱引用的智能指针,它的声明可以简化如下:
namespace boost { 。
template<typename T> class weak_ptr { public: template <typename Y> weak_ptr(const shared_ptr<Y>& r),
weak_ptr(const weak_ptr& r),
~weak_ptr(),
T* get() const; bool expired() const; shared_ptr<T> lock() const; }; } 。
可以看到,boost::weak_ptr必须从一个boost::share_ptr或另一个boost::weak_ptr转换而来,这也说明,进行该对象的内存管理的是那个强引用的boost::share_ptr。boost::weak_ptr只是提供了对管理对象的一个访问手段.
。
boost::weak_ptr除了对所管理对象的基本访问功能(通过get()函数)外,还有两个常用的功能函数:expired()用于检测所管理的对象是否已经释放;lock()用于获取所管理的对象的强引用指针.
通过boost::weak_ptr来打破循环引用 由于弱引用不更改引用计数,类似普通指针,只要把循环引用的一方使用弱引用,即可解除循环引用。对于上面的那个例子来说,只要把children的定义改为如下方式,即可解除循环引用:
class children { public: ~children() { std::cout <<"destroying children\n"; } 。
。
public: boost::weak_ptr<parent> parent; },
最后值得一提的是,虽然通过弱引用指针可以有效的解除循环引用,但这种方式必须在程序员能预见会出现循环引用的情况下才能使用,也可以是说这个仅仅是一种编译期的解决方案,如果程序在运行过程中出现了循环引用,还是会造成内存泄漏的。因此,不要认为只要使用了智能指针便能杜绝内存泄漏。毕竟,对于C++来说,由于没有垃圾回收机制,内存泄漏对每一个程序员来说都是一个非常头痛的问题.
最后此篇关于浅析Boost智能指针:scoped_ptr shared_ptr weak_ptr的文章就讲到这里了,如果你想了解更多关于浅析Boost智能指针:scoped_ptr shared_ptr weak_ptr的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我是 boost 库的新手,正在尝试 boost::scoped_ptr,它声明无法复制或移动此智能指针。但是我在玩一些代码时发现了一个问题。我能够创建 scoped_ptr 的新实例并使用现有的有效
我有一个具有以下结构的单例: // Hpp class Root : public boost::noncopyable { public: ~Root();
既然 scoped_ptr 保证给定线程中的所有对象都以类似堆栈的方式分配,那么为 scoped_ptr > , 事实上 std::vector*存储在 scoped_ptr 中与std::vecto
这个问题在这里已经有了答案: 关闭 9 年前。 Possible Duplicate: What is a smart pointer and when should I use one? 我正在阅
我有一个结构 typedef struct myStruct_st { int a; }myStruct; 可以使用创建 myStruct * myStruct_new() { printf(
假设我实现了一个scoped_ptr: template class scoped_ptr { public: scoped_ptr() = delete; explicit scoped
我的类的一个成员是 boost::scoped_ptr,它在创建对象时设置为 (T*)0。该类有一个 init() 方法,它实际上用一个新对象初始化智能指针。 但是,如果在智能指针具有有效引用之前抛出
谁能解释为什么这个例子中引用类型的转换失败了?我想使用 boost::scoped_ptr 作为缺少 std::unique_ptr 的解决方法。 struct A{}; struct B {
我很惊讶编译器拒绝编译这种代码: class A { virtual ~A() {} }; class B : public A { virtual ~B() {} void foo() {} };
我在 pagePtr.h 中有这样的东西 typedef int (*FunPtrType)(char* sz, unsigned int max_bytes, char* arg1, char* a
我正在尝试理解 boost::scoped_ptr 的语法.让我们定义并写入标准输出 a scoped_ptr指针及其指向的值: #include #include int main() {
通常我会遵循 Google 风格指南,我觉得它与我看待事物的方式非常吻合。我也几乎完全使用 boost::scoped_ptr 以便只有一个管理器拥有特定对象的所有权。然后我传递裸指针,我的想法是我的
检查以下代码: 这个有效: T *p = (std::find( this->first(), this->last(), *pPos )); if( p != last() ) { this
我正在使用可变参数模板,我想找到解压参数的好方法 template class MetaKernel : public MyKernel { public: MetaKernel (
我使用 boost::scoped_ptr 实现了一个简单的单例: template class Singleton : public boost::noncopyable { public:
所以我尝试围绕 boost.extension 函数创建一些包装器来创建类。所以我创建了一个函数: template boost::scoped_ptr get_class (shared_lib
我在像这样的小函数中使用 scoped_ptr。这样我就不必调用 delete 了。这是这种用法的矫枉过正吗?我的团队成员更喜欢原始指针和删除。如果这恰好用在非常关键的路径中,那么使用 scoped_
我刚刚开始使用 C++ boost 库。我在很多地方读到,当使用 scoped_ptr 时,即使出现异常,对象也总是被销毁。 They behave much like built-in C++ po
我正在研究智能指针,尤其是 scoped_ptr。我阅读了运算符 * 和 ->。我试着运行这段代码: int main(){ boost::scoped_ptrnumber(new int);
boost::scoped_ptr documentation包含一个称为 Handle/Body Idiom 的技术示例。它是用以下文字描述的: The scoped_ptr_example_tes
我是一名优秀的程序员,十分优秀!