C++11学习笔记——Dynamic memory management
来源:互联网 发布:windows live 账号注册 编辑:程序博客网 时间:2024/06/07 14:15
相比前面的类型支持(Type Support)部分,这部分的内容编程里相对来说使用频率更高,比如智能指针。
1.Smart pointers 智能指针
包含4个内容,unique_ptr/shared_ptr/weak_ptr/auto_ptr,其中前三个是C++11后纳入标准库的,更早的在boost或者<tr1/memory>中也有支持。
1.1 shared_ptr<T>
应该算是最常用的智能指针了,几乎所有的实现都采用在堆(heap)上放个计数值(count)的办法,当引用计数为0时则销毁其管理的资源,基本使用方法这里不再做多的说明。下面主要用代码的方式做一些特别说明:
A *a = new A(1);{ std::shared_ptr<A> p1(a); std::shared_ptr<A> p2(a);}p1和p2的引用资源实际上是分开的!当程序离开{}块的时候,p1对象离开{}块后引用计数编程0,将指针a的资源释放;p2对象离开{}块后执行同样的操作,但是指针a已经被析构掉了!!指针a这样就被析构两次,程序出现堆错误。正确的用法是如下:
std::shared_ptr<A> p1(new A(1));std::cout << p1.use_count() << std::endl;</span>
{//这里只是为了测试引用计数加的大括号 std::shared_ptr<A> p2(p1); std::cout << p1.use_count() << std::endl;}std::cout << p1.use_count() << std::endl;</span>
2)线程安全
shared_ptr引用计数本身是安全且无锁的,但对象的读写则不是,实际上 shared_ptr 有两个数据成员,一个用于保存指向实际对象的指针,另一个则是引用计数器。在进行shared_ptr赋值、拷贝构造、析构(写操作)的时候分了两步——先将指针指向实际对象,然后在引用计数器上+1,这样必然导致操作不是原子的。在多线程同时读写同一个智能指针对象时就必须加锁:
std::shared_ptr<A> p(new A);std::shared_ptr p1;// thread Ap1 = p; //读取p// thread Bp.reset(); //如果线程A读取p的同时线程B对p进行了写操作,那么会导致未知行为。
类似的还有同时写的时候也要加锁:
std::shared_ptr<int> p;// thread Ap.reset(new int(1));// thread Bp.reset(new int(2)); //同时写入或者:
// thread Ap1 = p; //增加一个引用计数// thread B// p同时已经离开了作用域,其管理的资源已经被析构了
1.2 unique_ptr<T>
唯一指针,unique_ptr<T>的更换保管对象必须由std::move或者reset()成员函数去实现。相比原有的std::auto_ptr<T>不会莫名其妙的发现原有的保管对象被销毁的情况(更为安全)。相比于shared_ptr<T>,该指针可以支持动态数组。
文档里对几种典型应用作了描述,概括起来就是对“生命周期内要求被唯一指针指向”的对象进行管理。说的比较抽象,本人倒是经常在开辟动态数组的时候使用:
int size = 10;std::unique_ptr<int[]> p1(new int[size]);
当p1离开作用域时,会自动调用delete[]对开辟的内存进行释放,这也从某方面贯彻了《Effective C++》里所讲的以对象管理内存资源的思想,省的new了之后忘记delete造成内存泄露。当然复杂点的场景也可以自己制定deleter。
1.3 weak_ptr<T>
A *a = new A(1);{ std::shared_ptr<A> p1(a); std::shared_ptr<A> p2(a);}由于p1销毁后p2不知道a的资源已经被释放了,造成再次访问出现问题,但是感觉正常来讲一般不会出现该情况。本人曾写过一个脱离框架的面向对象的定时器,由于Timer里面需要指定回调,为了解耦方便,本人用了std::function<void ()>去代替,但是如果指定了回调函数timeout_,那么假如指向的回调函数所在的对象被销毁了(而且函数内部使用的资源也被销毁了),那么当计时到了的时候调用timeout_就会出问题。为了解决该问题本人想了个偷懒的办法,既想很好的解耦又想方便代码的书写,于是就使用shared_ptr和weak_ptr,代码如下:
class Timer{public: void setTimeout(const std::shared_ptr<std::function<void ()> >& func) { timeout_ = func; } const std::weak_ptr<std::function<void ()> >& timeout() const { return timeout_; }private: std::weak_ptr<std::function<void ()> > timeout_; };
timeoutEvent(int timerfd){ ... //如果回调对象被删除了,根据weak_ptr的expired进行判断是否回调对象已经没了 if (!iter->second->timeout().expired()) { (*iter->second->timeout().lock())(); } ...}
- C++11学习笔记——Dynamic memory management
- Boost学习笔记 -- memory management
- Pointers on C——11 Dynamic Memory Allocation.1
- Pointers on C——11 Dynamic Memory Allocation.2
- Pointers on C——11 Dynamic Memory Allocation.3
- Pointers on C——11 Dynamic Memory Allocation.4
- Pointers on C——11 Dynamic Memory Allocation.5
- Pointers on C——11 Dynamic Memory Allocation.6
- c memory management(zz)
- C++ Memory Management
- Advanced Memory Management: Dynamic Allocation, Part 1
- IOS学习笔记之五:Memory Management 内存管理
- 【原】MIT在线课程学习笔记之《Introduction to C Memory Management and C++ Object-Oriented Programming》
- Memory management in C programs
- Memory management in C programs
- Memory management in C programs
- C++ 11 Memory Management
- Dynamic Memory Tensor Networks笔记
- HDU 4821 String 字符串HASH
- 大数运算
- 第12周项目4银行系统的简单模板
- Common Dbutils使用说明
- ECCV 2014 Oral Paper
- C++11学习笔记——Dynamic memory management
- 数据结构与算法分析笔记(6)——归并排序
- 嵌入式 Linux下比较全面的监控工具dstat
- acdream 1025Transform
- UVALive_6602_Counting Lattice Squares(公式推导)
- 第12周项目3 二进制转换
- AC算法原理与实现(模式匹配)
- 国外常见16款著名的实时网站统计系统
- 搭建GCC+JLINK开发调试环境(裸机调试)