c++智能指针 shared_ptr weak_ptr unique_ptr 语法 使用 实现

前言

c++最开始设计没有考虑gc(garbage collection)机制,后续c++11推出后STL标准库中增加了三个智能指针类,合理运用下可以让c++程序员摆脱忘记delete或者free的困扰
shared_ptr原理是引用计数,用于指针需要被传递复制的时候
weak_ptr主要就是为了配合shared_ptr防止出现循环引用(两个对象各持有各自的shared_ptr, 都无法先释放)
unique_ptr不可复制,离开作用域自动销毁,但是可以移动拷贝


一、语法使用

1.1 shared_ptr语法

// 测试类
class Test {
public:
	void test() {
	}
};

/* shared_ptr语法 */
// 1.初始化方式
std::shared_ptr<Test> sp(new Test()); // 正确,构造函数初始化

std::shared_ptr<Test> sp1 = std::make_shared<Test>(); // 正确,make_shared初始化

std::share_ptr<Test> sp2; 
sp2.reset(new Test()); // 正确,reset初始化

std::shared_ptr<Test> sp3 = new Test(); // 错误, shared_ptr是一个类,构造的sp是一个对象,不可以直接用指针赋值
									  // 除非重载赋值运算符=特殊处理,但是shared_ptr没有重载=

// 2.其他操作
Test sp1 = *sp; // 重载*运算符 获取原始指针实际值
sp->test(); //  重载->运算符 调用保存的原始指针成员函数
Test *sp2 = sp.get(); // 获取原始指针
if (sp) {} // 重载bool()函数,判断指针是否为空

1.2 weak_ptr语法

/* weak_ptr语法 */
// 1.初始化方式
std::shared_ptr<Test> sp(new Test());
std::weak_ptr<Test> sp_weak(sp); // 通过shared_ptr构造
std::weak_ptr<Test> sp_weak1 = sp;	// 通过shared_ptr赋值构造
std::weak_ptr<Test> sp_weak2(sp_weak); // 通过weak_ptr构造

// 2.其他操作
std::shared_ptr<Test> sp3 = sp_weak.lock(); // weak_ptr不能直接操作原始指针,需要的话需调用lock升级为shared_ptr
if (sp_weak.expired()) {} // 判断绑定的shared_ptr是否已析构

1.3 unique_ptr语法

/* unique_ptr语法 */
// 1.初始化方式
std::unique_ptr<Test> up(new Test()); // 构造函数初始化

std::unique_ptr<Test> up1 = std::make_unique<Test>(); // c11暂不支持,c17以后支持

std::unique_ptr<Test> up2; 
up2.reset(new Test()); // reset初始化

//2.其他操作

// 2.其他操作
Test up1 = *up; // 重载*运算符 获取原始指针实际值
up->test(); //  重载->运算符 调用保存的原始指针成员函数
Test *up2 = up.get(); // 获取原始指针
if (up) {} // 重载bool()函数,判断指针是否为空

1.4 三指针的区别
shared_ptr 和 unique_ptr在语法上没有区别,唯一的区别的是shared_ptr支持赋值共享,unique_ptr不允许赋值(原理是禁用赋值构造)但是可以引用传递
weak_ptr是专门用来解决shared_ptr循环引用的问题的,本身不能操作原始指针

二、shared_ptr代码实现

1.1 shared_ptr实现

#include <iostream>
using namespace std;

template <class T>
class shared_ptr {
private:
    // 保存真实指针
    T* ptr_;
    // 指向引用计数
    int* ref_count_; 

public:
    shared_ptr(T *t) {
        ptr_ = t;
        // 初始化引用计数
        if (ref_count_ == NULL) {
            ref_count_ = new int(1);
        }
    }

    shared_ptr(shared_ptr& ptr) {
        ptr_ = ptr->ptr_;
        // 引用计数加1
        ref_count_ = ptr->ref_count_;
        (*ref_count_)++;
    }

    void operator =(shared_ptr& ptr) {
        ptr_ = ptr->ptr_;
        // 引用计数加1
        ref_count_ = ptr->ref_count_;
        (*ref_count_)++;
    }
    
	T* get() {
		return ptr_;
	}

    T operator *() {
        return *ptr_;
    }

    T* operator ->() {
        return ptr_;
    } 
};

class A {
public:
    A() {}
    int test() {
        return 1;
    }
};

int main () {
    shared_ptr<A> sp(new A);
    cout << sp->test() << endl;
    return 0;
}

shared_ptr使用注意事项

  • 尽量不要使用get()获取原始指针,防止其他删除原指针造成double free
  • 如果类要返回this指针,最好使类继承enable_shared_from_this,然后 return shared_from_this();
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值