智能指针的底层实现

本文详细介绍了Boost库中几种智能指针(auto_ptr、scoped_ptr、shared_ptr)的实现原理及使用场景,包括资源管理机制、权限控制、引用计数等核心概念,并探讨了线程安全问题。

引入:定义一个类来封装资源的分配和释放,在构造函数完成资源的分配和初始化,在析构函数完成资源的清理。
boost库的智能指针
auto_ptr:资源转移,当使用拷贝构造,赋值操作时将资源转移,并将自己的资源置为空
加权限,当使用拷贝构造,赋值操作时资源不释放,只是将权限改为false,当权限为true时&&资源不为空时,才可以释放资源。
scoped_ptr:将拷贝构造,赋值操作设置为私有的或者保护的.
shared_ptr:采用引用计数的方式实现,每个对象都私有一个计数区域,表示多少个对象指向它。只有当_ptr不为空并且计数为1时才可以释放资源。
存在的线程安全问题
1. 同一个shared_ptr对象可以被多线程同时读取。
2. 不同的shared_ptr对象可以被多线程同时修改。
3. 同一个shared_ptr对象不能被多线程直接修改,但可以通过原子函数完成。
实现代码

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
//auto_ptr权限转移
template<class T>
class AutoPtr
{
private:
    T* _ptr;
public:
    AutoPtr(T* ptr = NULL)
        :_ptr(ptr)
    {}
    AutoPtr(AutoPtr<T>& at)
        :_ptr(at._ptr)
    {
        at._ptr = NULL;
    }
    AutoPtr<T>& operator=(AutoPtr<T>& at)
    {
        if (this != &at)
        {
            delete _ptr;
            _ptr = at._ptr;
            at._ptr = NULL;
        }
        return *this;
    }
    T& operator*()const
    {
        return *(_ptr);
    }
    T* operator->()const
    {
        return _ptr;
    }
    ~AutoPtr()
    {
        if (_ptr != NULL)
        {
            delete _ptr;
            _ptr = NULL;
        }
        cout << "~AutoPtr()" << endl;
    }
};
template<class T>
class AutoPtrTwo
{
private:
    T* _ptr;
    mutable bool _owner;//加权限,当有权限时才能释放资源,否则不可以
public:
    AutoPtrTwo(T* ptr = NULL)
        :_ptr(ptr)
        , _owner(true)
    {}
    AutoPtrTwo(const AutoPtrTwo<T>& at)
        :_ptr(at._ptr)
        , _owner(true)
    {
        at._owner = false;
    }
    AutoPtrTwo<T>& operator=(const AutoPtrTwo<T>& at)
    {
        if (this != &at)
        {
            if (_owner)
                delete _ptr;
            _ptr = at._ptr;
            _owner = at._owner;
            at._owner = false;
        }
        return *this;
    }
    T& operator*()const
    {
        return *(_ptr);
    }
    T* operator->()const
    {
        return _ptr;
    }
    ~AutoPtrTwo()
    {
        if (_ptr  && _owner)
        {
            delete _ptr;
            _ptr = NULL;
        }
        cout << "~AutoPtrTwo()" << endl;
    }
};
//scoped_ptr,防拷贝实现
template<class T>
class ScopedPtr
{
private:
    T* _ptr;
private:
    ScopedPtr(const ScopedPtr<T>& sp);
    ScopedPtr<T>& operator=(const ScopedPtr<T>& sp);
public:
    ScopedPtr(T* ptr = NULL)
        :_ptr(ptr)
    {}
    T& operator*()const
    {
        return *(_ptr);
    }
    T* operator->()const
    {
        return _ptr;
    }
    ~ScopedPtr()
    {
        if (_ptr)
        {
            delete _ptr;
            _ptr = NULL;
        }
    }
};
//shared_ptr,采用引用计数
template<class T>
class SharedPtr
{
private:
    T* _ptr;
    mutable int* _pCount;
public:
    SharedPtr(T* ptr = NULL)
        :_ptr(ptr)
    {
        if (_ptr)
            _pCount = new int(1);
    }
    SharedPtr(const SharedPtr<T>& sdp)
        :_ptr(sdp._ptr)
        , _pCount(new int(1))
    {
        ++(*_pCount);
    }
    SharedPtr<T>& operator=(const SharedPtr<T>& sdp)
    {
        if (this != &sdp)
        {
//          if (_ptr && (--(*_pCount) == 0))
//          {
//              delete _ptr;
//              _ptr = NULL;
//              delete _pCount;
//              _pCount = NULL;
//          }
            Realease();
            ++*(sdp._pCount);
        }
        return *this;
    }
    T& operator*()const
    {
        return *(_ptr);
    }
    T* operator->()const
    {
        return _ptr;
    }
    ~SharedPtr()
    {
        Realease();
        cout << "~SharedPtr()" << endl;
    }
private:
    void Realease()
    {
        if ((_ptr) && (--(*this->_pCount) == 0))
        {
            delete _pCount;
            _pCount = NULL;
            delete _ptr;
            _ptr = NULL;
        }
    }
};

测试代码

#include "Ptr.hpp"


void TestAutoPtr()
{
    int a = 10;
    int* p=&a;
    AutoPtr<int> at;
    AutoPtr<int> at1(p);
    AutoPtr<int> at2(at1);
    at = at2;
}
void TestAutoPtrTwo()
{
    int b = 20;
    int* pt = &b;
    AutoPtrTwo<int> att;
    AutoPtrTwo<int> att1(pt);
    AutoPtrTwo<int> att2(att1);
    att = att2;
}

void TestSocpedPtr()
{
    //int a = 30;
    int* p3 = new int(14);
    //int *p3 = &a;
    ScopedPtr<int> sp;
    ScopedPtr<int> sp1(p3);
    cout << *sp1 << endl;
}
void TestSharedPtr()
{
    int* p4 = new int(50);
    SharedPtr<int> sdp;
    SharedPtr<int> sdp1(p4);
    SharedPtr<int> sdp2(sdp1);
    sdp = sdp2;

}

int main()
{
    //TestAutoPtr();
    //TestAutoPtrTwo();
    //TestSocpedPtr();
    TestSharedPtr();

    return 0;
}
### 关于 `std::shared_ptr` 的底层实现 `std::shared_ptr` 是 C++ 中的一种智能指针,用于管理动态分配的对象并自动处理对象生命周期。其核心功能依赖于控制块(control block),该结构体保存着引用计数和其他必要信息。 #### 控制块设计 为了支持多线程环境下的安全操作以及弱引用机制,通常会有一个独立的控制块来跟踪强引用和弱引用的数量: ```cpp struct ControlBlock { unsigned int strong_refs; unsigned int weak_refs; explicit ControlBlock(): strong_refs(1), weak_refs(0) {} void add_strong_ref() { ++strong_refs; } bool remove_strong_ref() { return --strong_refs == 0; } void add_weak_ref() { ++weak_refs; } bool remove_weak_ref() { return --weak_refs == 0; } }; ``` 此部分定义了一个简单的控制块类[^2]。 #### 构造函数与析构函数 当创建一个新的 `std::shared_ptr` 实例时,除了初始化指向目标对象的原始指针外,还需要为其关联一个新构建的控制块实例;而在销毁 `std::shared_ptr` 对象之前,则需先判断当前是否为最后一个持有者,并据此决定是否释放资源。 ```cpp template<typename T> class SharedPtr { private: T* _ptr; ControlBlock* _ctrl_blk; public: // Constructor that takes raw pointer and creates control block. explicit SharedPtr(T* ptr): _ptr(ptr), _ctrl_blk(new ControlBlock()) {} ~SharedPtr() noexcept { if (_ctrl_blk->remove_strong_ref()) delete _ptr; if (_ctrl_blk->remove_weak_ref()) delete _ctrl_blk; } // Copy constructor implements shared ownership semantics by incrementing the reference counts. SharedPtr(const SharedPtr& other): _ptr(other._ptr), _ctrl_blk(other._ctrl_blk) { _ctrl_blk->add_strong_ref(); } // Move constructor transfers ownership without changing existing state. SharedPtr(SharedPtr&& other) noexcept : _ptr(nullptr), _ctrl_blk(nullptr){ swap(*this, other); } // Assignment operators follow similar logic as constructors but also handle self-assignment cases properly. friend void swap(SharedPtr<T>& lhs, SharedPtr<T>& rhs) { using std::swap; swap(lhs._ptr, rhs._ptr); swap(lhs._ctrl_blk, rhs._ctrl_blk); } }; // Note: This simplified version does not cover all aspects like thread safety or support for custom deleters. ``` 上述代码展示了如何通过引入控制块来实现基本版本的 `std::shared_ptr` 功能。 对于更复杂的场景,比如循环引用问题,在某些情况下可能会导致内存泄漏。为了避免这种情况的发生,可以考虑采用侵入式智能指针或其他解决方案,如使用 `boost::intrusive_ptr` 或者调整对象之间的关系以打破潜在的环形依赖链路[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值