[学习笔记]智能指针

介绍

  • 会自动delete(不会导致内存泄漏)
  • 智能指针是class
  • c++11智能指针均在库memory中

基本操作

std::auto_ptr

c++11中被彻底放弃,被std::unique_ptr取代

  • 初始化
auto_ptr<T> ptr(new T(value));
auto_ptr<T> ptr;
ptr.reset(new T(value));
  • 访问方式
ptr->ClassFunciton();
ptr.get()->ClassVariable;
(*ptr).ClassVariable;
  • 判断智能指针是否为空
if(ptr.get()==NULL)
  • 存在潜在的内存崩溃问题:赋值 or 复制后原指针为NULL(悬空),不能再使用
    • 赋值:a=b——最好不使用赋值操作符=
      • auto_ptr管理的对象不能放入vector等stl容器
      • auto_ptr最好不要当成参数传递
    • 复制:auto_ptr ptr1(ptr2);
  • 释放指针
T* tmp = ptr.release(); delete tmp; //release()函数只是让出内存所有权
ptr.reset();

std::unique_ptr

能达到boost::scoped_ptr的效果

  • 初始化
unique_ptr<T> ptr(new T(value));
unique_ptr<T> ptr;
ptr.reset(new T(value));
//better (c++14)
unique_ptr<T> ptr=make_unique<T>(value);
  • 判断智能指针是否为空
if(ptr.get()==nullptr)
  • 禁止复制语义,即独享所有权:复制和赋值都被标记为delete
    • 特例:可以通过函数返回一个unique_ptr
    • 转移堆内存:移动构造 std::move
unique_ptr<T> ptr2(move(ptr1));
unique_ptr<T> ptr3=move(ptr1);

array

  • 初始化
unique_ptr<T[]> ptr(new T[N]);
unique_ptr<T[]> ptr;
ptr.reset(new T[N]);
unique_ptr<T[]> ptr(make_unique<T[]>(N));

std::shared_ptr

  • 用于共享所有权:在内部使用了引用计数:ptr.use_count()
    • 一旦ptr.use_count()计数器变为0, 就会自动释放自己所管理的对象
  • 初始化
shared_ptr<T> ptr(new T(value));
shared_ptr<T> ptr;
ptr.reset(new T(value));
//better (c++14)
shared_ptr<T> ptr=make_shared<T>(value);
  • 可以复制、赋值
  • 释放指针
T* tmp = ptr.release(); //use_count()会-1

std::enable_shared_from_this

在类中返回包含当前对象的一个shared_ptr对象供外部使用

class A:public enable_shared_from_this<A>{
public:
    shared_ptr<A> getSelf(){
        return shared_from_this();
    }
};
int main(){
    shared_ptr<A> ptr1(new A());
    shared_ptr<A> ptr2=ptr1->getSelf();

    return 0;
}
  • 应避免enable_shared_from_this的循环引用问题

std::weak_ptr

  • shared_ptr的Observer对象
    • 只对shared_ptr进行引用,而不改变其引用计数
    • 当被观察的shared_ptr失效后,相应的weak_ptr也相应失效
    • 可用来解决shared_ptr相互引用时的死锁问题
  • 初始化
shared_ptr<T> sPtr(new T(value));
weak_ptr<T> wPtr(sPtr);
shared_ptr<T> sPtr(new T(value));
weak_ptr<T> wPtr=sPtr;
  • 没有重写->和*,也没有get()函数,因此不能直接操作对象
  • 检测shared_ptr
if (wPtr.expired()) return;//返回true说明其引用的资源已经不存在了

shared_ptr<T> sPtr=wPtr.lock();
if(sPtr){
    //对sPtr进行操作
}
  • eg.观察者模式
class Subscriber{
};

class SubscribeManager{
public:
    void publish(){
        for(const auto &iter : m_subscribers){
            if (!iter.expired()){
                //给订阅者发送消息
            }
        }
    }
private:
    vector<weak_ptr<Subscriber> > m_subscribers;
};

使用原则

  • 一旦一个对象使用智能指针管理后,就不该再使用原始裸指针去操作
  • 作为类成员变量时,应该优先使用前置声明

参考

posted @ 2022-01-17 16:30  Aireen_Ye  阅读(150)  评论(0编辑  收藏  举报
底部 顶部 留言板 归档 标签
Der Erfolg kommt nicht zu dir, du musst auf den Erfolg zugehen.