c++11特性(2):智能指针及其实现

4 篇文章 0 订阅


智能指针

unique_ptr

unique_ptr持有对对象的独有权,同一时刻只能有一个unique_ptr指向对象(通过禁止拷贝语义,只有移动语义来实现)
生命周期:从创建开始,直到离开作用域
离开作用域时,若其指向对象,则将其所指对象销毁(默认使用delete操作符,用户可指定其他操作)
unique_ptr实际是类模板,只不过是禁用了拷贝构造函数、赋值运算符=
重写了移动拷贝构造、->符号、*符号
独占指针的手工实现

/*
手工实现独占指针
*/

/*
unique_ptr特性
1. 独享所有权
2. 重置对象 reset()
3. 对象不可复制,不能通过=号进行复制
4. 通过std::move转移对象所有权
5. 释放关联指针release()
6. get()仅仅返回关联指针(强制delete该返回指针后,独占指针在销毁时会出错-段错误)
*/
#pragma once
#include <stdio.h>
#include <iostream>

using namespace std;

template<typename T>
class SmartPointer
{
private:
public:
  //构造函数
  SmartPointer(T* ptr_ = nullptr): m_ptr(ptr_){}
  //支持移动拷贝构造
  SmartPointer(SmartPointer &&p) noexcept : m_ptr(p.m_ptr)
  {
    cout << "移动拷贝" << endl;
    p.m_ptr = nullptr;
  }
  //禁用拷贝构造函数
  SmartPointer(const SmartPointer &ptr_) = delete;

  //析构函数
  ~SmartPointer()
  {
    if (m_ptr)
    {
      delete m_ptr;
      m_ptr = nullptr;
    }
  }
  //重载->符号
  T* operator->() const noexcept{return m_ptr;}
  //重载 * 符号
  T& operator* () const noexcept{return *m_ptr;}
  //禁用赋值运算符
  SmartPointer &operator = (const SmartPointer &p) = delete;
  //释放智能指针地址
  T* release() noexcept{
    T *res = m_ptr;
    m_ptr = nullptr;
    return res;
  }
  //将托管指针重置为传入的指针
  void reset(T* p = nullptr) noexcept{
    std::swap(m_ptr, p);
    delete p;
  }
  //swap
  void swap(SmartPointer &p) noexcept{
    std::swap(m_ptr, p.m_ptr);
  }
  //获取被管理对象的指针
  T* get(){
    return m_ptr;
  }
  //存放智能指针
  T* m_ptr;
};

shared_ptr

共享指针,共享指针可以实现多个智能指针指向相同对象,使用计数机制来表明资源被几个指针共享,当我们release时,当前指针会释放资源所有权,计数-1。当计数为0时,资源会被释放。

/*
手动实现shared_ptr共享指针
*/

/*
共享指针
1. 每使用一次,内部引用计数加1
2. 每析构一次,内部引用计数减1
3. 引用计数减为0时自动释放原生指针所指向的内存
*/
#pragma once
#include <stdio.h>
#include <iostream>

using namespace std;

template <typename T>
class Shared_ptr
{
private:
  //引用计数
  int *count;
  //指针
  T* _ptr;
public:
  //构造函数
  Shared_ptr():count(0), _ptr((T*)0){}
  //从原生指针构造
  Shared_ptr(T* p):count(new int(1)), _ptr(p){}
  //拷贝构造函数,引用计数器+1,让该对象的指针指向形参对象的指针
  Shared_ptr(Shared_ptr<T>& other):count(&(++ *other.count)), _ptr(other._ptr){}

  //重载->
  T* operator->(){return _ptr;}
  //重载*
  T& operator*() {return *_ptr;}
  //重载 =
  //如果原来shared_ptr已经有对象,则让其引用次数减1并判断引用是否为0(是否调用delete)
  //然后将新的对象引用次数加1
  Shared_ptr<T>& operator= (Shared_ptr<T>& other)
  {
    //如果是自己赋给自己,则直接返回
    if (this == &other)
      return *this;

    //计数器加1
    ++*other.count;
    if (this->_ptr && 0 == --*this->count)
    {
      delete count;
      delete _ptr;
      cout << "delete ptr = " << endl;
    }

    this->_ptr = other._ptr;
    this->count = other.count;
    return *this;
  }

  //析构函数,使引用次数减一并判断引用是否为0(是否调用delete)
  ~Shared_ptr()
  {
    //判断ptr是否为空,并且count--后是否为0
    if (_ptr && --*count == 0)
    {
      delete count;
      delete _ptr;
      cout << "delete ptr ~" << endl;
    }
  }
  //返回引用次数
  int use_count(){return *count;}
};

weak_ptr

weak_ptr是为配合shared_ptr而引入的一种智能指针来协助shared_ptr工作,他可以从一个shared_ptr或另一个weak_ptr对象构造,他的构造和析构不会引起引用计数的增加或减少。没有重载*和->但可以使用lock获得一个可用的shared_ptr对象

weak_ptr的使用更为复杂一点,他可以指向shared_ptr指针指向的对象内存,却并不拥有该内存,而使用weak_ptr成员lock,则可返回其指向内存的一个shared_ptr对象,且在所指对象内存已经无效时,返回指针空值nullptr
使用例程

void check(weak_ptr<int> &wp)
{
    shared_ptr<int> sp = wp.lock(); // 转换为shared_ptr<int>
    if (sp != nullptr)
    {
        cout << "still " << *sp << endl;
    }
    else
    {
        cout << "pointer is invalid" << endl;
    }
}
 
int main()
{
    shared_ptr<int> sp1(new int(22));
    shared_ptr<int> sp2 = sp1;
    weak_ptr<int> wp = sp1; // 指向shared_ptr<int>所指对象
 
    cout << "count: " << wp.use_count() << endl; //打印计数器
    cout << *sp1 << endl;   // 22
    cout << *sp2 << endl;   // 22
 
    check(wp);              // still 22
 
    sp1.reset();
    cout << "count: " << wp.use_count() << endl;
 
    cout << *sp2 << endl;   // 22
    check(wp);              // still 22
 
    sp2.reset();
    cout << "count: " << wp.use_count() << endl;
    check(wp);              // pointer is invalid
 
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值