C++智能指针的实现及原理
一、原因
动态内存的管理需要程序员手动申请和释放,动态内存的分配和释放用new和delete运算符来完成,如果new和delete的操作次数不一致,则会造成内存泄漏、二次释放等问题,为了更加方便和安全地使用动态内存,c++11引入了智能指针的概念
二、概念
智能指针是指能够自动释放所指向的对象的指针,它本质上不是一个指针,而是封装了一个普通指针的类对象,其设计思想来源于“RAII”,即“资源获取就是初始化”,通过一个对象,在其构造时获取资源,在其生命周期结束自动调用析构函数释放所指向的对象,使用智能指针需要include<memory>头文件</memory>
三、分类
1.auto_ptr
同一时刻只有一个指针指向实际对象,不支持拷贝和赋值操作
2.unique_ptr
同一时刻只有一个unique_prt指向一个给定对象,也不支持拷贝和赋值操作,可以使用move转移所有权
unique_ptr<int> p3 = std::move(p1); //现在那块内存归p3所有, p1成为无效的指针
3.shared_ptr
多个指针可以指向同一个对象,每个shared_ptr都有一个关联的计数器,用来表示所指向的对象被引用的次数,支持赋值和拷贝,当计数器为0时对象会被释放(可以使用make_shared函数初始化。不能将指针直接赋值给一个智能指针,因为一个是类,一个是指针)
4.weaked_ptr
一种不控制所指向对象生存期的智能指针,它指向一个由shared_ptr管理的对象,将一个weak_ptr绑定到一个shared_ptr不会改变shared_ptr的引用计数。一旦最后一个指向对象的shared_ptr被销毁,对象就会被释放,即使有weak_ptr指向对象,对象还是会被释放。
int main() { { std::shared_ptr<int> sh_ptr = std::make_shared<int>(10); std::cout << sh_ptr.use_count() << std::endl; std::cout << *sh_ptr<< std::endl; //获得指针的值 std::weak_ptr<int> wp(sh_ptr);//弱指针可以观测资源的使用情况 std::cout << wp.use_count() << std::endl; if(!wp.expired()){ //lock()函数,从被观测的shared_ptr获得一个可用的 std::shared_ptr<int> sh_ptr2 = wp.lock(); //shared_ptr对象, 从而操作资源 *sh_ptr = 100; std::cout << wp.use_count() << std::endl; } } //delete memory }
四、实现shared_ptr
template<typename T> class sharedptr { public: //构造函数 sharedptr(T *ptr):_ptr(ptr),_cnt(new int(1)) { cout << "构造" << endl; } //拷贝构造 sharedptr(sharedptr<T> sp):_ptr(sp._ptr),_cnt(sp._cnt){ cout << "拷贝构造" << endl; ++(*_cnt); } //赋值操作运算符 sharedptr<T> operator=(sharedptr<T> sp) { cout << "赋值操作运算符" << endl; if (_ptr != sp._ptr) { if (--(*_cnt) == 0) {//计数器为0,则释放指针指向的对象 delete _ptr; delete _cnt; } _ptr = sp._ptr; _cnt = sp._cnt; ++(*_cnt); } return *this; } T * operator->() { return _ptr; } T& operator*() { return *_ptr; } int getcnt() { return *_cnt; } ~sharedptr(){ cout << "析构" << endl; if (--(*cnt) == 0) { delete _ptr; _ptr = nullptr; delete _cnt; _cnt = nullptr; } } private: int *_cnt; T *_ptr; };