unique_ptr的模拟实现

#include<iostream>
#include<memory>

using namespace std;
class Int {
private:
    int _val;
public:
    Int() :_val(0) { cout << "无参的构造函数" << endl; }
    explicit Int(int val) :_val(val) {
        cout << "Int()" << endl;
    }
    ~Int() {
        cout << "~Int()" << endl;
    }
    int& Value() {
        return _val;
    }
    void PrintInt()const {
        cout << _val << endl;
    }
    const int& Value()const {
        cout << _val << endl;
    }
    Int& operator=(const Int& other) {
        cout << "operator=()" << endl;
        if (this != &other) {
            this->_val = other._val;
        }
        return *this;
    }
    Int(const Int& other) :_val(other._val){
        cout << "拷贝构造" << endl;
    }
};

namespace yolo{
    template<class _Ty>
    struct my_default_deleter{
        void operator()(_Ty* p)const {
            delete p;
        }
    };
    template<class _Ty>//专门针对数组的模板特化(为特定的类型提供特殊的实现)
    struct my_default_deleter<_Ty[]> {
        void operator()(_Ty* p)const {
            delete[]p;
        }
    };







    template<class _Ty,class _Dx = my_default_deleter<_Ty> >
    class uniquePtr {
    public:
        using element_type = _Ty;
        using pointer = _Ty*;
        using deleter_type = _Dx;
    private:
        pointer mPtr;
        deleter_type mDeleter;
    public:
        uniquePtr(const uniquePtr&) = delete;//unique_ptr没有拷贝构造和赋值
        uniquePtr& operator=(const uniquePtr&) = delete;
        uniquePtr(uniquePtr&& other) {//移动构造不要写const uniquePtr&&other,因为你要动他(转移它的资源)
            mPtr = other.mPtr;
            other.mPtr = nullptr;
        }
        uniquePtr& operator=(uniquePtr&& other) {//移动赋值也是动资源
            if (this != &other) {
                //1.
                //delete mPtr;
                //mPtr = other.mPtr;
                //other.mPtr = nullptr;
                //2.
                reset(other.release());
            }
            return *this;
        }
        explicit uniquePtr(pointer p = nullptr) :mPtr(p) { cout << "uniquePtr()" << endl; }
        ~uniquePtr() {
            reset();
        }
        pointer release() {
            pointer old = mPtr;
            mPtr = nullptr;
            return old;
        }
        pointer get()const {
            return mPtr;
        }
        _Dx& get_deleter(){
            return mDeleter;//返回删除器对象
        }
        const _Dx& get_deleter()const {
            return mDeleter;
        }
        void reset(pointer p = nullptr) {
            if (mPtr) {
                mDeleter(mPtr);//mDeleter.operator()(this->mPtr);
            }
            mPtr = p;
        }
        void swap(uniquePtr& it) {
            std::swap(it.mPtr, this->mPtr);
            std::swap(it.mDeleter, this->mDeleter);
        }
        explicit operator bool()const {
            return mPtr != nullptr;
        }
        _Ty* operator->()const {
            return mPtr;
        }
        _Ty& operator*()const {
            return *mPtr;
        }
    };


    template<class _Ty, class _Dx>
    class uniquePtr<_Ty[],_Dx> {
    public:
        using element_type = _Ty;
        using pointer = _Ty*;
        using deleter_type = _Dx;
    private:
        pointer mPtr;
        deleter_type mDeleter;
    public:
        uniquePtr(const uniquePtr&) = delete;//unique_ptr没有拷贝构造和赋值
        uniquePtr& operator=(const uniquePtr&) = delete;
        uniquePtr(uniquePtr&& other) {//移动构造不要写const uniquePtr&&other,因为你要动他(转移它的资源)
            mPtr = other.mPtr;
            other.mPtr = nullptr;
        }
        uniquePtr& operator=(uniquePtr&& other) {//移动赋值也是动资源
            if (this != &other) {
                //1.
                //delete mPtr;
                //mPtr = other.mPtr;
                //other.mPtr = nullptr;
                //2.
                reset(other.release());
            }
            return *this;
        }
        explicit uniquePtr(pointer p = nullptr) :mPtr(p) { cout << "uniquePtr()" << endl; }
        ~uniquePtr() {
            reset();
        }
        pointer release() {
            pointer old = mPtr;
            mPtr = nullptr;
            return old;
        }
        pointer get()const {
            return mPtr;
        }
        _Dx& get_deleter() {
            return mDeleter;//返回删除器对象
        }
        const _Dx& get_deleter()const {
            return mDeleter;
        }
        void reset(pointer p = nullptr) {
            if (mPtr) {
                mDeleter(mPtr);//mDeleter.operator()(this->mPtr);
            }
            mPtr = p;
        }
        void swap(uniquePtr& it) {
            std::swap(it.mPtr, this->mPtr);
            std::swap(it.mDeleter, this->mDeleter);
        }
        explicit operator bool()const {
            return mPtr != nullptr;
        }
        _Ty* operator->()const = delete;//数组不再允许使用箭头和解引用访问
        _Ty& operator*()const = delete;//转而加一个[]访问
        _Ty& operator[](const size_t i)const {
            //此处也可以加越界检查
            return mPtr[i];//return get()[i];
        }

    };


}
void test() {
    yolo::uniquePtr<Int> ap(new Int(10));
    yolo::uniquePtr<Int[]> bp(new Int[10]);
    //    template<class _Ty,class _Dx = my_default_deleter<_Ty> >    class uniquePtr{};
    //    template<class _Ty, class _Dx>    class uniquePtr<_Ty[],_Dx>{};

    //test函数中第二行:模板参数将会匹配特化条件,编译器会优先选择特化版本。此时_Dx用泛化版本的_Dx的缺省值
    //然后把“my_default_deleter<_Ty>”中的_Ty换成_Ty[]
    bp[0].PrintInt();
    bp[0].Value() = 90;
    bp[0].PrintInt();
    bp[99].PrintInt();//15110712:注意我们调用operator[]()时并没有做越界检查,没有检查size_t i的范围,
    //这不是我们不想做,是无能为力做,我们可以将i<0的抛异常,
    //但是i最大是多少呢?我们不知道!我们只知道我们这个智能指针管理了一组对象,这个组有多大,并不知道

}
int main() {
    test();
}

unique_ptrC++11 标准提供的智能指针,用于管理动态分配的对象。它使用了独占所有权的概念,保证了在不再需要指针时自动释放资源,从而避免了内存泄漏。 手撕 unique_ptr实现涉及到指针的拷贝和移动语义。下面是一个简单的手撕 unique_ptr 的示例代码: ```cpp template <typename T> class unique_ptr { public: explicit unique_ptr(T* ptr = nullptr) : ptr_(ptr) {} ~unique_ptr() { delete ptr_; } unique_ptr(const unique_ptr&) = delete; // 禁用拷贝构造函数 unique_ptr& operator=(const unique_ptr&) = delete; // 禁用拷贝赋值运算符 unique_ptr(unique_ptr&& other) noexcept : ptr_(other.ptr_) { other.ptr_ = nullptr; } unique_ptr& operator=(unique_ptr&& other) noexcept { if (this != &other) { delete ptr_; ptr_ = other.ptr_; other.ptr_ = nullptr; } return *this; } T& operator*() const { return *ptr_; } T* operator->() const { return ptr_; } T* get() const { return ptr_; } private: T* ptr_; }; ``` 上述代码中,我们定义了一个类模板 `unique_ptr`,它模拟了标准库中的 `std::unique_ptr` 功能。在构造函数中,我们接受一个指针作为参数,并将其保存在 `ptr_` 成员变量中。析构函数负责释放指针所指向的资源。为了遵循独占所有权的原则,我们禁用了拷贝构造函数和拷贝赋值运算符,而使用移动语义来实现赋值操作。`operator*` 和 `operator->` 用于重载解引用操作符,方便使用指针指向的对象。 需要注意的是,上述实现只是一个简单的手撕版 unique_ptr,并没有处理更复杂的边界情况和异常安全性。在实际使用中,建议使用标准库提供的 `std::unique_ptr`,它已经经过了充分测试和优化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值