拷贝构造采用的方式是:将一个对象中指针所指的所有属性复制给被拷贝的对象。为了防止出现内存泄漏,需要被拷贝对象,重新申请一片堆空来存放所指之物。
移动构造是一个对象中的指针所指转移给被移动对象。因此需要将前者对他所拥有的数据的拥有权释放。
普通赋值:如 obja = base,是是将base中的指针所指赋值一份给obja。
移动就是直接转移给obja,base对资源的拥有权释放。
其实c11新引入的移动赋值和移动构造都是"右值引用"的概念的产生而产生,实际针对的是对对资源和系统内部资源进行转移引入的引入的一个新的概念。(实现的是资源的转移)
unique_ptr(唯一性)智能指针,一次只能指向一个对象。
share_ptr(共享性)智能指针,多个指针可以指向同一个对象。 但是必须记录有多少个指针指向了同一个对象。
int main(void)
{
std::shared_ptr<Object> sp1(new Object(10));
return 0;
}
当两个指针同时指向同一个对象时,那么指向的引用计数就会加一。
int main(void)
{
std::shared_ptr<Object> sp1(new Object(10));
std::shared_ptr<Object> sp2(sp1);
return 0;
}
shared_ptr提供了两个函数来检查其共享的引用计数值,分别是unique()和use_count()。
use_count()函数,该函数返回当前指针的引用计数值。值得注意的是use_count()函数可能效率很低,应该只把它用于测试或调试。
unique()函数用来测试该shared_ptr是否是原始指针唯一拥有者,也就是use_count()的返回值为1时返回true,否则返回false。
std::shared_ptr<Object> sp1 = std::make_shared<Object>(10);
std::shared_ptr<Object> sp2(new Object(10));
cout << sp1.use_count() << endl;
cout << sp2.unique() << endl;
std::shared_ptr<Object> sp2(new Object(10));
//需要创建两个对象,一个是引用计数对象,一个是object对象
std::shared_ptr<Object> sp1 = std::make_shared<Object>(20);
//只创建了一次对象。
第一种,需要构建两次对象,所以就要析构两次
第二种, 只创建一次对象,只析构一次。Object完成初始化,op2直接指向既可以。
template<class _Ty>
class MyDeletor
{
public:
MyDeletor() = default;
void operator()(_Ty* ptr) const
{
if (ptr != nullptr)
{
delete ptr;
}
}
};
class MyDeletor<_Ty[]>
{
public:
MyDeletor() = default;
void operator()(_Ty* ptr) const
{
if (ptr != nullptr)
{
delete[]ptr;
}
}
};
template<typename _Ty>
class RefCnt
{
private:
_Ty* mptr; // 指向对象的指针
int ref; // 引用计数
public:
RefCnt(_Ty* p = nullptr) : mptr(p), ref(mptr != nullptr)
{
}
~RefCnt() {}
};
指向一个对象的my_share_ptr
template<class _Ty, class _Dx = MyDeletor<_Ty> >
class my_shared_ptr
{
public:
my_shared_ptr(_Ty* p = nullptr) :ptr(nullptr)
{
if (p != nullptr)
{
ptr = new RefCnt(p);
}
}
private:
RefCnt<_Ty>* ptr; //指向计数器的指针
_Dx mDeletor; //删除器
};
由于是共享型智能指针,所以会让多个指针指向同一个对象,因此判断智能指针对象中ptr指针是否为空,如果不为空,对ptr->ref+1
my_share_ptr(const my_share_ptr& _Y):ptr(_Y.ptr) //让sp2中的指针指向sp1中指针所指之物。
{ //将sp1的资源复制给sp2
if (ptr != NULL)
{
ptr->ref += 1;
}
}
my_share_ptr(my_share_ptr&& _Y):ptr(_Y.ptr) //移动构造相当于直接操作sp1的值(sp1被做右值),直接将sp1的值给ptr
{
_Y.ptr = NULL; //将sp1的中指针的指向置为空。(就是将sp1的资源转移给sp2)
}
完成赋值需要满足的条件:
if (this == &_Y || this->ptr == _Y.ptr) return *this;
my_share_ptr<Object>op1(new Object(5));
my_share_ptr<Object>op2(new Object(5));
op1 = op1;
op1 = op2;
2.if (ptr != NULL && --ptr->ref == 0)
my_share_ptr<Object>op1(new Object(5));
my_share_ptr<Object>op2(new Object(10));
op2 = op1;
my_share_ptr& operator=(const my_share_ptr& _Y) //将sp1中的值复制给sp2
{
if (this == &_Y || this->ptr == _Y.ptr) return *this;
if (ptr != NULL && --ptr->ref == 0)
{
mDeletor(ptr);
}
ptr = _Y.ptr;
if (ptr != nullptr)
{
ptr->ref += 1;
}
return *this;
}
int main()
{
my_share_ptr<Object>op1;
my_share_ptr<Obbject>op2(new Object(10));
op2 = op1;
}
int main()
{
my_unique_ptr<Object>sp1(new Object(5));
my_unique_ptr<Object>sp2;
my_unique_ptr<Object>sp3;
my_unique_ptr<Object>sp1(new Object(10));
sp2 = sp3; //NULL = NULL
sp2 = sp1; //NULL = 非 NULL
sp1 = sp3; //非 NULL = NULL
sp2 = sp4; //非 NULL = 非 NULL
}
my_share_ptr& operator =(my_share_ptr&& _Y) //将sp1的资源转移给sp2
{
//判断是否是同一个对象?
if (this == &_Y) return *this;
//判断各自的指针是否指向同一个对象,如果相等,在判断两个指向是否为空
if (ptr == _Y.ptr && ptr != NULL && _Y.ptr != NULL)
{
ptr->ref -= 1;
_Y.ptr = NULL;
return *this;
}
//若没有指向同一个对象,判断ptr是否为空,如果不为空,并且ptr指向了一个对象
if (ptr != NULL && --ptr->ref == 0)
{
MDeletor(ptr); //断开ptr对该对象的拥有权
}
ptr = _Y.ptr;
_Y.ptr = NULL;
return *this;
}
int main()
{
my_unique_ptr<Object>sp1(new Object(5));
my_unique_ptr<Object>sp3(sp1);
my_unique_ptr<Object>sp2(sp1);
sp1 = std::move(sp2); //采用移动构造,会将sp2移除
}
1.判断当前指针是否为空,并且指向一个对象。如果符合,调用删除器,解绑。
2.当前指针重新向堆区引用计数的结构,该结构的指着指向参数类的对象。
void reset(_Ty* p = nullptr)
{
if (this->ptr != nullptr && --this->ptr->ref == 0)
{
mDeletor(ptr);
}
ptr = new RefCnt<_Ty>(p);//先调用RefCnt中的构造函数创建不具名对象,并给对mptr进行初始化,返回RefCnt的对象地址给ptr
}
1.判断当前ptr是否为空,以及是否指向一个对象。满足条件,调用删除器,删除ptr指向的引用计数对象的mptr指针指向的对象。在删除ptr。
2.将ptr置为空。
~my_shared_ptr()
{
if (this->ptr != nullptr && --this->ptr->ref == 0)
{
mDeletor(ptr->mptr);
delete ptr;
}
ptr = nullptr;
}
_Ty* get() const { return ptr->mptr; }
_Ty& operator*() const
{
return *get();
}
_Ty* operator->() const
{
return get();
}
size_t use_count() const
{
if (this->ptr == nullptr) return 0;
return this->ptr->ref;
}
void swap(my_shared_ptr& r)
{
std::swap(this->ptr, r.ptr);
}
特点:
1.删除一组对象是,对于删除操作,我们都要先删除,当前指针所指的引用计数对象中的指针mptr所指。
2.在删除ptr指针。多个指针指向一组对象。
改下如下:
if (ptr != nullptr && --ptr->ref == 0)
{
mDeletor(ptr->mptr);
delete ptr;
}
_Ty& operator[](const int idx) const
{
return ptr->mptr[idx];
}
template<class _Ty>
class MyDeletor
{
public:
//MyDeletor() = default;
MyDeletor() {}
void operator()(_Ty* ptr) const
{
if (ptr != nullptr)
{
delete ptr;
}
}
};
template<class _Ty>
class MyDeletor<_Ty[]>
{
public:
MyDeletor() = default;
void operator()(_Ty* ptr) const
{
if (ptr != nullptr)
{
delete[]ptr;
}
}
};
template<class _Ty>
class RefCnt
{
public:
_Ty* mptr;
int ref;
//std::atomic_int ref;
public:
RefCnt(_Ty* p = nullptr) :mptr(p), ref(mptr != nullptr) {}
~RefCnt() {}
};
template<class _Ty, class _Dx = MyDeletor<_Ty> >
class my_shared_ptr // thread;
{
public:
my_shared_ptr(_Ty* p = nullptr) :ptr(nullptr)
{
if (p != nullptr)
{
ptr = new RefCnt(p);
}
}
my_shared_ptr(const my_shared_ptr& _Y) :ptr(_Y.ptr)
{
if (ptr != nullptr)
{
ptr->ref += 1;
}
}// my_shared_ptr
my_shared_ptr(my_shared_ptr&& _Y) :ptr(_Y.ptr)
{
_Y.ptr = nullptr;
}// my_shared_ptr
operator bool() const { return ptr != nullptr; }
my_shared_ptr& operator=(const my_shared_ptr& _Y) //
{
if (this == &_Y || this->ptr == _Y.ptr) return *this;
if (ptr != NULL && --ptr->ref == 0)
{
mDeletor(ptr);
}
ptr = _Y.ptr;
if (ptr != nullptr)
{
ptr->ref += 1;
}
return *this;
}
my_shared_ptr& operator=(my_shared_ptr&& _Y) // move operator =
{
if (this == &_Y) return *this;
if (this->ptr == _Y.ptr && this->ptr != nullptr && _Y.ptr != nullptr)
{
this->ptr->ref -= 1;
_Y.ptr = nullptr;
return *this;
}
if (this->ptr != nullptr && --ptr->ref == 0)
{
mDeletor(ptr);
}
ptr = _Y.ptr;
_Y.ptr = nullptr;
return *this;
}
void reset(_Ty* p = nullptr)
{
if (this->ptr != nullptr && --this->ptr->ref == 0)
{
mDeletor(ptr);
}
ptr = new RefCnt<_Ty>(p);
}
~my_shared_ptr()
{
if (this->ptr != nullptr && --this->ptr->ref == 0)
{
mDeletor(ptr->mptr);
delete ptr;
}
ptr = nullptr;
}
_Ty* get() const { return ptr->mptr; }
_Ty& operator*() const
{
return *get();
}
_Ty* operator->() const
{
return get();
}
size_t use_count() const
{
if (this->ptr == nullptr) return 0;
return this->ptr->ref;
}
void swap(my_shared_ptr& r)
{
std::swap(this->ptr, r.ptr);
}
private:
RefCnt<_Ty>* ptr;
_Dx mDeletor;
};
template<class _Ty, class _Dx >
class my_shared_ptr<_Ty[], _Dx>
{
public:
my_shared_ptr(_Ty* p = nullptr) :ptr(nullptr)
{
if (p != nullptr)
{
ptr = new RefCnt(p);
}
}
my_shared_ptr(const my_shared_ptr& _Y) :ptr(_Y.ptr)
{
if (ptr != nullptr)
{
ptr->ref += 1;
}
}// my_shared_ptr
my_shared_ptr(my_shared_ptr&& _Y) :ptr(_Y.ptr)
{
_Y.ptr = nullptr;
}// my_shared_ptr
operator bool() const { return ptr != nullptr; }
my_shared_ptr& operator=(const my_shared_ptr& _Y) //
{
if (this == &_Y || this->ptr == _Y.ptr) return *this;
if (ptr != NULL && --ptr->ref == 0)
{
mDeletor(ptr->mptr);
delete ptr;
}
ptr = _Y.ptr;
if (ptr != nullptr)
{
ptr->ref += 1;
}
return *this;
}
my_shared_ptr& operator=(my_shared_ptr&& _Y) // move operator =
{
if (this == &_Y) return *this;
if (this->ptr == _Y.ptr && this->ptr != nullptr && _Y.ptr != nullptr)
{
this->ptr->ref -= 1;
_Y.ptr = nullptr;
return *this;
}
if (this->ptr != nullptr && --ptr->ref == 0)
{
mDeletor(ptr->mptr);
delete ptr;
}
ptr = _Y.ptr;
_Y.ptr = nullptr;
return *this;
}
void reset(_Ty* p = nullptr)
{
if (this->ptr != nullptr && --this->ptr->ref == 0)
{
mDeletor(ptr->mptr);
delete ptr;
}
ptr = new RefCnt<_Ty>(p);
}
~my_shared_ptr()
{
if (this->ptr != nullptr && --this->ptr->ref == 0)
{
mDeletor(ptr->mptr);
delete ptr;
}
ptr = nullptr;
}
_Ty* get() const { return ptr->mptr; }
_Ty& operator*() const
{
return *get();
}
_Ty* operator->() const
{
return get();
}
size_t use_count() const
{
if (this->ptr == nullptr) return 0;
return this->ptr->ref;
}
void swap(my_shared_ptr& r)
{
std::swap(this->ptr, r.ptr);
}
_Ty& operator[](const int idx) const
{
return ptr->mptr[idx];
}
private:
RefCnt<_Ty>* ptr;
_Dx mDeletor;
};