C++ 之实现自己的 unique_ptr

1. 几个基本成员函数的作用:

u.reset()   释放u指向的对象
u.reset(q)  如果提供了内置指针q,就令u指向这个对象 
u.reset(nullptr) 将 u 置为空
u.release()   u 放弃对指针的控制权,返回指针,并将 u 置为空

2. 一些规则:

  1. 某个时刻只能有一个unique_ptr 指向一个给定的对象。当它销毁时,它所指向的对象也会被销毁。
  2. 初始化 unique_ptr 只能采用直接初始化的方式 (explicit 关键字)
  3. 不支持复制构造与赋值操作
  4. 在创建或者是reset一个具有删除器的unique_ptr 时,必须提供删除器
  5. 不支持拷贝与赋值的规则有一个例外,那就是我们可以拷贝或者赋值一个将要被销毁的unique_ptr(右值引用) ,比如:
/* 从函数返回一个unique_ptr */
unique_ptr<int> clone(int p ){
    return unique_ptr<int>(new int(p));
}
/* 返回一个局部对象的拷贝 */
unique_ptr<int> clone(int p ){
    unique_ptr<int> ret(new int (p));
    return ret ;
}
  1. noexcept :在C++11中,声明一个函数不可以抛出任何异常使用关键字noexcept.

3. unique_ptr使用场景

1、为动态申请的资源提供异常安全保证
2、返回函数内动态申请资源的所有权
3、在容器中保存指针
4、管理动态数组
5、作为auto_ptr的替代品 
             /*unique_ptr.h 文件 */
#ifndef _UNIQUE_PTR_H
#define __UNIQUE_H
class Delete {   
public:
    template<typename T>
    void operator()(T *p) const {
        delete  p;
    }
};
template<typename T,typename D = Delete >
class unique_ptr {
public:
    explicit unique_ptr(T *pp = nullptr ,const D &dd= D() )
        :un_ptr(pp),del(dd)
        {  
        }
    ~unique_ptr() { 
        del(un_ptr); 
    } 
    /* 不支持拷贝与赋值   */
    unique_ptr(const unique_ptr&) = delete ;
    unique_ptr& operator=(const unique_ptr& ) = delete ;

    /*可以拷贝或者赋值一个将要被销毁的 unique_ptr(右值引用)*/
    unique_ptr( unique_ptr&& right_value):
        un_ptr(right_value.un_ptr),del(std::move(right_value.del)) {
        right_value.un_ptr = nullptr ;
    }
    unique_ptr& operator=( unique_ptr&& right_value ) noexcept {
        if(this != &right_value ){
            std::cout << "operator && right_value " << std::endl ;
            del(*this);
            un_ptr = right_value.un_ptr;
            del = std::move(right_value.del);
            right_value.un_ptr =  nullptr ;
        }
        return *this ;
    }
    //u.release()   u 放弃对指针的控制权,返回指针,并将 u 置为空
    T* release(){ 
        T *tmp = un_ptr ;
        un_ptr = nullptr ;
        return  tmp  ;
    }
    /*
    u.reset()   释放u指向的对象
    u.reset(q)  如果提供了内置指针q,就令u指向这个对象 
    u.reset(nullptr) 将 u 置为空
    */
    void reset(){  del(un_ptr); }
    void reset(T* q  ){ 
        if( un_ptr ){
            del(un_ptr) ;
            un_ptr = q ;
        }
        else 
            un_ptr = nullptr ; 
    }
    void swap(unique_ptr &other ) noexcept {
        using std::swap ; 
        swap( un_ptr,other.un_ptr );
        swap(del,other.del) ;
    } 
    T* get() { return un_ptr ; }
    D& get_deleter(){ return  del ; }
    T& operator*()  { return *un_ptr ; }
    T* operator->() { return  un_ptr ; }
private:
    T *un_ptr = nullptr ;
    D del ;
};
#endif
            /*    main.cpp 文件  */
#include <iostream>
#include <string>
//#include"shared_ptr.h"
#include "unique_ptr.h"
#include"DebugDelete.h"
#include <assert.h>
struct Foo {
    Foo() { std::cout << "Foo()\n"; }
    ~Foo() { std::cout << "~Foo()\n"; }
    Foo(const Foo&) { std::cout << "Foo copy ctor\n"; }
    Foo(Foo&&) { std::cout << "Foo move ctor\n"; }
};
struct Fooo {
    Fooo(int n = 0) noexcept : bar(n) { std::cout << "Fooo: constructor, bar = " << bar << '\n'; }
    ~Fooo() { std::cout << "Fooo: destructor, bar = " << bar << '\n'; }
    int GetBar() const noexcept { return bar; }
private:
    int bar;
};
struct D {
    void bar() { std::cout << "Call deleter D::bar()...\n"; }
    void operator()(Foo* p) const
    {
        std::cout << "Call delete from function object...\n";
        delete p;
    }
};
using namespace std ;
int main()
{
    unique_ptr<string> p1(new string("Shengxi-Liu"));
    cout << *p1 << endl ;
      {
        std::cout << "======================\nunique_ptr constructor:\n";
        unique_ptr<Foo> up1;
        unique_ptr<Foo> up1b(nullptr);
        unique_ptr<Foo> up2(new Foo);

        DebugDelete d;
        unique_ptr<Foo, DebugDelete> up3(new Foo, d);
        unique_ptr<Foo, DebugDelete&> up3b(new Foo, d);
        unique_ptr<Foo, DebugDelete> up4(new Foo, DebugDelete());
        unique_ptr<Foo> up5b(std::move(up2));
        unique_ptr<Foo, DebugDelete> up6b(std::move(up3));

        unique_ptr<Foo> up7 = std::move(up5b);
        Foo* fp = up7.release();
        assert(up7.get() == nullptr);
        delete fp;

        up6b.reset(new Foo());
        up6b.reset(nullptr);

        unique_ptr<Fooo> up71(new Fooo(1));
        unique_ptr<Fooo> up72(new Fooo(2));

        up71.swap(up72);

        std::cout << "up71->val:" << up71->GetBar() << std::endl;
        std::cout << "up72->val:" << (up72.get())->GetBar() << std::endl;

        unique_ptr<Foo, D> up8(new Foo(), D());
        D& del = up8.get_deleter();
        del.bar();
    }
}

这里写图片描述
参考:https://www.cnblogs.com/DswCnblog/p/5628195.html

posted @ 2018-06-13 00:10  Tattoo_Welkin  阅读(362)  评论(0编辑  收藏  举报