练习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(字节)