栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

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

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

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

文章目录
      • 智能指针
        • unique_ptr
        • shared_ptr
        • weak_ptr


智能指针

unique_ptr

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



#pragma once
#include 
#include 

using namespace std;

template
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时,资源会被释放。



#pragma once
#include 
#include 

using namespace std;

template 
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& other):count(&(++ *other.count)), _ptr(other._ptr){}

  //重载->
  T* operator->(){return _ptr;}
  //重载*
  T& operator*() {return *_ptr;}
  //重载 =
  //如果原来shared_ptr已经有对象,则让其引用次数减1并判断引用是否为0(是否调用delete)
  //然后将新的对象引用次数加1
  Shared_ptr& operator= (Shared_ptr& 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 &wp)
{
    shared_ptr sp = wp.lock(); // 转换为shared_ptr
    if (sp != nullptr)
    {
        cout << "still " << *sp << endl;
    }
    else
    {
        cout << "pointer is invalid" << endl;
    }
}
 
int main()
{
    shared_ptr sp1(new int(22));
    shared_ptr sp2 = sp1;
    weak_ptr wp = sp1; // 指向shared_ptr所指对象
 
    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;
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/849320.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号