C++11__共享型智能指针的一种靠谱的简易实现
实现共享型智能指针的关键在于共享计数,这里利用资格资源管理类实现共享计数的相关操作。
一、实现代码
以下代码提供了一种规范的共享型智能指针简单实现,注释应该比较清楚。
#pragma once
#include<utility>//std::swap
//资源管理类
class SharedCount
{
public:
SharedCount() noexcept : _count(1) {}//资源取得时便是初始化时机
void AddCount() {
++_count;
}
//Redeuce需要有返回值,便于智能指针类析构函数使用
long ReduceCount()noexcept {
return --_count;
}
//获取计数
long GetCount() const noexcept{
return _count;
}
private:
long _count;
};
template<typename T>
class SmartPtr {
public:
//模板的各个实例之间不具有friend关系,因而不能互访私有成员
//需要显示声明友元
template<typename U>
friend class SmartPtr;
//构造函数,不支持参数隐式转换
explicit SmartPtr(T* ptr = nullptr):_ptr(ptr)
{
if (_ptr) {
_shared_count = new SharedCount();
std::cout << "Defult Constructor! " << *_ptr << std::endl;
}
else std::cout << "Defult Constructor!(nullptr) "<< std::endl;
}
//拷贝构造,必须有非泛型版本,防止编译器自动生成缺省版本
SmartPtr(const SmartPtr& oth)
{
_ptr = oth._ptr;
if (_ptr) {
oth._shared_count->AddCount();
_shared_count = oth._shared_count;
std::cout << "Copy Constructor! " << *_ptr << std::endl;
}
else std::cout << "Copy Constructor!(nullptr) " << std::endl;
}
//析构函数
~SmartPtr()
{
//如果_ptr不为空且计数为0,则delete
if (_ptr && !_shared_count->ReduceCount())
{
std::cout << "Destructor! " << *_ptr << std::endl;
delete _ptr;
delete _shared_count;
}
else std::cout << "Destructor!(nullptr) " << std::endl;
}
//移动构造
template<typename U>
SmartPtr(SmartPtr<U>&& oth)
{
_ptr = oth._ptr;
if (_ptr) {
_shared_count = oth._shared_count;
oth._ptr = nullptr;
std::cout << "Move Constructor! " << *_ptr << std::endl;
}
else std::cout << "Move Constructor!(nullptr) " << std::endl;
}
//泛型版本拷贝构造
template<typename U>
SmartPtr(const SmartPtr<U>& oth)
{
_ptr = oth._ptr;
if (_ptr) {
oth._shared_count->AddCount();
_shared_count = oth._shared_count;
std::cout << "Template Copy Constructor! " << *_ptr << std::endl;
}
else std::cout << "Template Copy Constructor!(nullptr) " << std::endl;
}
template<typename U>
SmartPtr(const SmartPtr<U>& oth,T* ptr) noexcept
{
_ptr = oth._ptr;
if (_ptr) {
oth._shared_count->AddCount();
_shared_count = oth._shared_count;
}
}
//重载赋值,pass by value,传递副本(常用技巧)
SmartPtr& operator=(SmartPtr rhs) noexcept
{
rhs.Swap(*this);//交换副本和*this
return *this;
}
void Swap(SmartPtr& rhs) noexcept
{
using std::swap;
swap(_ptr, rhs._ptr);
swap(_shared_count, rhs._shared_count);
}
T* Get() const noexcept
{
if (_ptr) return _ptr;
else return nullptr;
}
long UseCount() const noexcept
{
if (_ptr) {
return _shared_count->GetCount();
}
else return 0;
}
T& operator*() const noexcept
{
return *_ptr;
}
T* operator->() const noexcept
{
return _ptr;
}
private:
T* _ptr;
SharedCount* _shared_count;
};
//全局的智能指针对象Swap
template <typename T>
void Swap(SmartPtr<T>& lhs,SmartPtr<T>& rhs) noexcept
{
lhs.Swap(rhs);
}
//简易版本二
template<typename T>
struct newFree {
void operator()(T* ptr) {
if (ptr != nullptr) {
delete ptr;
ptr = nullptr;
}
}
};
template<typename T>
struct mallocFree {
void operator()(T* ptr) {
if (ptr != nullptr) {
free(ptr);
ptr = nullptr;
}
}
};
template<typename T, typename DF = newFree<T>>
class Sptr {
private:
T* ptr_;
mutex mtx_;
int* cnt_;
public:
Sptr(T* ptr = nullptr):ptr_(ptr) {
unique_lock<mutex> lock(mtx);
if (ptr != nullptr) {
cnt_ = new int(1);//RAII
}
}
Sptr(const Sptr& sp) {
ptr_ = sp.ptr_;
cnt_ = sp.cnt_;
unique_lock<mutex> lock(mtx);
if (ptr_) {
++(*cnt_);
}
}
~Sptr() {
unique_lock<mutex> lock(mtx);
if (ptr_) {
DF()(ptr_);
delete cnt_;
cnt_ = nullptr;
}
}
//pass by value
Sptr& operator=(Sptr sp) {
sp.Swap(*this);
return *this;
}
void Swap(Sptr& sp) {
swap(ptr_, sp.ptr_);
swap(cnt_, sp.cnt_);
}
};
二、简单测试
#include <iostream>
#include"SmartPtr.h"
using namespace std;
int main()
{
SmartPtr<char> pc;//默认构造
SmartPtr<char> pc0 = SmartPtr<char>();//移动构造
SmartPtr<char> pc1(new char('a'));//初值构造
SmartPtr<char> pc2(pc1);//拷贝构造
SmartPtr<char> pc3(new char('b'));
SmartPtr<char> pc4;
SmartPtr<char> pc5(new char('c'));
pc5 = pc4;//pc5引用计数为0,析构掉。
pc1 = pc3;//正常赋值
pc1 = pc1;//自我赋值
cout << "pc0.count = " << pc0.UseCount() << " pc0: nullptr" << endl;
cout << "pc1.count = " << pc1.UseCount() << " pc1: " << *pc1.Get() << endl;
cout << "pc2.count = " << pc2.UseCount() << " pc2: " << *pc2.Get() << endl;
cout << "pc3.count = " << pc3.UseCount() << " pc3: " << *pc3.Get() << endl;
return 0;
}
三、运行结果