1628437

练习16.28:

编写你自己版本的shared_ptr和unique_ptr。

【出题思路】

本题练习定义复杂的类模板。

【解答】

对于shared_ptr(我们的版本命名为SP),关于引用计数的管理、拷贝构造函数和拷贝赋值运算符等的设计,参考HasPtr即可。

对于unique_ptr (我们的版本命名为UP),无须管理引用计数,也不支持拷贝构造函数和拷贝赋值运算符,只需设计release和reset等函数实现资源释放即可。

#ifndef SP_H
#define SP_H
#include <iostream>
using namespace std;

template <typename T>      
class SP {   
public:
    SP():p(nullptr), use (nullptr) {}  
    explicit SP(T* pt):p(pt), use(new size_t(1)) {}
    SP (const SP &sp):
    p(sp.p), use (sp.use) { if(use) ++ *use; } // 拷贝构造函数
    SP& operator=(const SP&);              // 拷贝赋值运算符
    ~SP();
    T& operator*(){ return *p; }       // 解引用
    T& operator*() const{ return *p; } // const 版
private:     
    T *p;     
    size_t *use;
};
    
template <typename T>
SP<T>::~SP()
{
    if(use && --*use == 0) {
        //如果引用计数变为0
        delete p;   // 释放对象内存
        delete use; // 释放计数器内存
    }
}

template <typename T>
SP<T>& SP<T>::operator= (const SP<T> &rhs)
{
    if(rhs.use)
        ++*rhs.use; //递增右侧运算对象的引用计数
    if(use && --*use == 0) {
        //然后递减本对象的引用计数
        delete p;      //如果没有其他用户
        delete use;  //释放本对象分配的成员
    }
    p = rhs.p;		//拷贝指针
    use = rhs.use;      
    return *this;	//返回本对象
}

template <typename T, class... Args>
SP<T> make_SP(Args&&... args)
{
    return SP<T>(new T(std::forward<Args>(args)...));
}

template <typename T>   
class UP {
    public:   
    UP () : p(nullptr) {}
    UP (const UP &) = delete;			// 禁止拷贝构造函数
    explicit UP (T* pt) : p (pt) {}		// 构造函数  
    UP& operator= (const UP&) = delete;	// 禁止拷贝赋值运算符
    ~UP ();
    T* release ();						// 交出控制权
    void reset (T *new_p);				// 释放对象
    T& operator* () { return *p; }		// 解引用运算符
    T& operator* () const { return *p; }// const 版
private:
    T *p;
};

template <typename T>      
UP<T>::~UP ()      
{
    if(p)			// 如果已经分配了空间
        delete p;	// 释放对象内存
}

template <typename T>      
void UP<T>::reset(T *new_p)  
{  
    if(p)
        delete p;	// 释放对象内存
    p = new_p;		// 指向新对象
}
                    
template <typename T>  
T* UP<T>::release()    
{
    T *q = p;
    p = nullptr;// 清空指针
    return q;	// 返回对象指针
}
#endif

int main()
{
    return 0;
}

本页共101段,4385个字符,5090 Byte(字节)