使用智能指针首先要引用头文件
#include<memory>
内存泄漏
shared_ptr是用来解决c++中内存泄漏的问题
什么是内存泄漏呢
内存泄漏
内存泄漏就是我们从堆区申请的一块空间,没有对这块空间进行释放,导致这块空间既不能被重新利用,也不能被找到。
什么会导致内存内存呢
未释放动态分配的内存
shared_ptr循环引用,引用计数可能永远不会降为0.
虚析构,在继承关系中,编译器会把基类与派生类的构造函数同名,此时析构函数为函数隐藏,只会调用指针类型里的析构函数发生内存泄漏。
内存泄漏会导致很多问题,比如长时间运行,性能变差,程序莫名被挂掉,越界等问题
怎么解决内存泄漏的问题
- 使用智能指针,shared_ptr,unique_ptr,可以在对象生命周期结束自动释放
- RAII思想,RAII指的就是确保资源在对象构造的时候获得,被析构掉的时候自动释放资源。
- 使用工具检测内存泄漏,Valgrind,cppcheck等检测工具。
内存泄漏如何定位
- 静态的分析工具,cppcheck,可以在编译阶段检测一些潜在的内存泄漏问题
- 动态分析工具,Valgrind在Linux系统上较为常用,
- 编写自定义的内存分析器
shared_ptr
shared_ptr是一种引用计数思想,当多个指针指向同一对象的时候,这时候对象的引用计数加一,当对象的引用计数为0的时候说明,没有指针再指向这块内存了,我们就要把这块内存释放掉。
实现shared_ptr
#include<iostream>
#include<memory>
using namespace std;
template<class T>//实现智能指针
/*
无参构造:传递指针构造,拷贝构造,移动构造,移动赋值
reset()替换对象,销毁对象
operator*()
get()获取原始指针
use_count获得引用计数
*/class Ref {int r_count = 0;T* obj = nullptr;
public:Ref():{}Ref(T* target) :obj(target) {r_count++;}//引用计数加1inline void increase() {r_count++;}//引用计数减一inline vopid reduce() {r_count--;if (r_count == 0) {delete obj;delete this;}}T* get() {return obj;}int getCount() {return r_count;}};template<class T>
class Shared_ptr {Ref<T>* ref = nullptr;
public:Shared_ptr() = default;~Shared_ptr() {if (ref)ref->reduce();}Shared_ptr(T* newP) {cout << "构造函数---------" << endl;ref = new Ref<T>(newP);}Shared_ptr(const Shared_ptr& other) {cout << "拷贝构造函数---------" << endl;this->ref = other.ref;if (ref)ref->increase();}Shared_ptr(Shared_ptr&&other) {cout << "移动构造---------" << endl;ref = other.ref;other.ref = nullptr;}//给已经存在的对象赋值Shared_ptr& operator=(const Shared_ptr& other) {cout << "赋值函数---------" << endl;if (ref) {ref->reduce();}ref = other.ref;if (ref) {ref->increase();}return *this;}Shared_ptr& operator=(Shared_ptr&& other) {cout << "移动赋值---------" << endl;if (ref) {ref->reduce();}ref = other.ref;other.ref = nullptr;return *this;}void reset(T*target) {if (ref)ref->reduce();ref = neww Ref<T>(target);}void reset() {if (ref)ref->reduce();ref = nullptr;}T& operator*() {return *ref->get();}T* operator->() {if (ref) {return ref->get();}}int user_count() {if (ref)return ref->getCount();else return 0;}
};
weak_ptr
weak_ptr指针指向对象的时候,并不会导致对象的引用计数加一,因为weak_ptr是用来检测当前对象的引用计数为多少,用他来获取shared_ptr中的一些信息。查看shared_ptr指向的堆区内存是否被释放掉
weak_ptr用来解决shared_ptr多个对象之间交叉有对方类型的引用,导致引用计数可能永远不会为0的循环引用问题
通常不单独使用,只能和shared_ptr联合使用,
unique_ptr
独享所有权的智能指针,提供了严格意义上的所有权
当该对象被销毁时,会在其析构函数中删除关联的原始指针。