智能指针 C++里面的四个智能指针: auto_ptr
, unique_ptr
,shared_ptr
, weak_ptr
其中后三个是C++11支持,并且第一个已经被C++11弃用 。
简介 智能指针主要用于管理在堆上分配的内存 ,它将普通的指针封装为一个栈对象。当栈对象的生存周期结束后,会在析构函数中释放掉申请的内存,从而防止内存泄漏。C++ 11中最常用的智能指针类型为shared_ptr,它采用引用计数的方法,记录当前内存资源被多少个智能指针引用。该引用计数的内存在堆上分配。当新增一个时引用计数加1,当过期时引用计数减一。只有引用计数为0时,智能指针才会自动释放引用的内存资源。对shared_ptr进行初始化时不能将一个普通指针直接赋值给智能指针,因为一个是指针,一个是类。可以通过make_shared函数或者通过构造函数传入普通指针。并可以通过get函数获得普通指针。
为什么要使用智能指针 智能指针的作用是管理一个指针,因为存在以下这种情况:申请的空间在函数结束时忘记释放,造成内存泄漏 。使用智能指针可以很大程度上的避免这个问题,因为智能指针是一个类,当超出了类的实例对象的作用域时,会自动调用对象的析构函数,析构函数会自动释放资源。所以智能指针的作用就是在函数结束时自动释放内存空间,不需要手动释放内存空间 。
unique_ptr unique_ptr实现独占式拥有 或严格拥有概念,保证同一时间内只有一个智能指针可以指向该对象 。它对于避免资源泄露(例如“以new创建对象后因为发生异常而忘记调用delete”)特别有用。
因此,unique_ptr不允许拷贝 ,具体看示例代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 class Entity {public : Entity(){ cout <<"construct Entity" <<endl ; } ~Entity(){ cout <<"析构函数 " <<endl ; } }; auto test (unique_ptr <Entity> uptr) { cout <<"test funtion begin!" <<endl ; { unique_ptr <Entity> tmp = std ::move(uptr); uptr = std ::move(tmp); } return uptr; } int main (int argc, const char *argv[]) { cout <<"main funtion begin!" <<endl ; auto uptr = make_unique<Entity>(); auto res = test(std ::move(uptr)); cout <<"main will end!" <<endl ; return 0 ; }
shared_ptr shared_ptr实现共享式拥有 概念。多个智能指针可以指向相同对象 ,该对象和其相关资源会在“最后一个引用被销毁”时候释放 。从名字share就可以看出了资源可以被多个指针共享,它使用计数机制来表明资源被几个指针共享。可以通过成员函数use_count()来查看资源的所有者个数 。除了可以通过new来构造,还可以通过传入auto_ptr, unique_ptr,weak_ptr来构造。当我们调用release()时,当前指针会释放资源所有权,计数减一。当计数等于0时,资源会被释放 。
成员函数: use_count 返回引用计数的个数 (long)
unique 返回是否是独占所有权( use_count 为 1 //true or false)
swap 交换两个 shared_ptr 对象(即交换所拥有的对象)
reset 放弃内部对象的所有权或拥有对象的变更, 会引起原有对象的引用计数的减少
get 返回内部对象(指针), 由于已经重载了()方法, 因此和直接使用对象是一样的
手写smartPointer sharepointer 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 #include <iostream> #include <vector> template <class T >class SharePointer {private : class Implement { public : T * _ptr; size_t _count; Implement(T* p):_ptr(p),_count(1 ){} ~Implement(){ delete _ptr; } }; Implement * mImplement; public : SharePointer(T* p):mImplement(new Implement(p)){} ~SharePointer(){ decrease(); } SharePointer(const SharePointer& other):mImplement(other.mImplement){ increase(); } SharePointer& operator =(const SharePointer& other){ if (mImplement != other.mImplement){ decrease(); mImplement = other.mImplement; increase(); } return this ; } T* operator ->()const { return mImplement->_ptr; } T& operator *()const { return *(mImplement->_ptr); } size_t use_count () { return mImplement->_count; } private : void decrease () { if (!mImplement->_count)delete mImplement; else mImplement->_count--; } void increase () { mImplement->_count++; } }; class test {public : test(int value) { this ->a = value; } test(const test& p) { this ->a = p.a; } int a = 20 ; void print () { std ::cout << "a = " << a << std ::endl ; } }; int main (int argc, const char * argv[]) { SharePointer<test> p = new test(20 ); std ::cout <<p.use_count()<<std ::endl ; { SharePointer<test>t = p; std ::cout <<p.use_count()<<std ::endl ; p->print(); } std ::cout <<p.use_count()<<std ::endl ; return 0 ; }