一、C++的STL
1. 智能指针
1.1. auto_ptr
(无论什么情况下都不要使用,C++98标准,到了C++11标注引入了shared_ptr,unique_ptr,,weak_ptr)
1.2. shared_ptr
shared_ptr和auto_ptr最大的区别就是,shared_ptr解决了指针间共享对象所有权的问题,也就是auto_ptr中的赋值的奇怪问题。所以满足了容器的要求,可以用于容器中。而auto_ptr显然禁止共享对象所有权,不可以用于容器中。
(1)默认构造函数,函数参数为变量地址
(2)拷贝构造函数,函数参数为引用
(3)重载函数operator*
(4)重载函数operator->
(5)重载函数operator=,使之可以进行隐性转换操作,注:实际C++源码中是没有这个的,构造函数用关键字explicit声明,在定义对象时必须显示调用初始化式,不能使用赋值操作符进行隐式转换。
(6)空函数判断
(7)引用次数统计函数
注意:使用shared_ptr也要引用头文件#include<memory>,如下使用简单的源码实现
#ifndef _SHARED_PTR_H
#define _SHARED_PTR_H
/*
一个模板T* ptr,指向实际的对象
一个引用次数
重载operator*和operator->,使得能像指针一样使用share_ptr
重载copy constructer,使其引用次数加一
重载operator=,如果原来的shared_ptr已经有对象
*/
template<typename T>
class shared_ptr
{
public:
shared_ptr(T* p) : count(new int(1)),_ptr(p);//默认的构造函数,必须自己显示的开辟内存
shared_ptr(shared_ptr<T>& p):count(&(++p.count)),_ptr(p.ptr);//拷贝构造函数,属于强制转换,显式
T& operator*();//
T* operator->();
shared_ptr<T> & operator=(shared_ptr<T>& p);//重载等号,保证保存同为shared_ptr的指针能够互转,等号计数器减1,右边计数器加1.
~shared_ptr();
bool empty();//检查是否指向同一个空T
int GetCount();
private:
int *count;//引用计数器
T* _ptr;//每创建一个对象,则有一个指针指向一个shared_ptr的类型
};
#include"_shared_ptr.h"
template<typename T>
shared_ptr<T>::shared_ptr(T* p=nullptr):count(new int(1)),_ptr(p)//默认的构造函数,显式开辟内存
{
if(_ptr){
count = new int(1);//如果初始化不为空,则计数器为1
}else{
count = new int(0);//如果初始化为空,则计数器为0
}
}
template<typename T>
shared_ptr<T>::shared_ptr(shared_ptr<T>&p):count(&(++p.count)),_ptr(p.ptr)//拷贝构造函数,属于强制转换,显式
{
if(this != p)
{
this->_ptr = p._ptr;
this->count = p.count;
*(this->count)++;
}
}
template<typename T>
T& shared_ptr<T>::operator*(){
return *(this->_ptr);
}
template<typename T>
T* shared_ptr<T>::operator->(){
return this->_ptr;
}
template<typename T>
shared_ptr<T>& shared_ptr<T>::operator=(shared_ptr<T>& p){
//重载等号,保证保存同为shared_ptr的指针能相互转化,等号左边计数器减1,右边计数器加1.
++*(p.count);//等式右边引用次数加1,左边引用次数减1
if(this->_ptr && 0 == --*this->count) //当左边引用次数为0
{
delete count;
delete _ptr;
}
this->count = p.count;
this->_ptr = p._ptr;
return *this;
}
template<typename T>
bool shared_ptr<T>::empty()//检查是否有一个指向空T,当为空的时候,count必须为0
{
return _ptr == nullptr;
}
template<typename T>
int shared_ptr<T>::GetCount()
{
return *count;
}
1.3. unique_ptr
unique_ptr的构造函数与auto_ptr一样,构造函数采用explicit声明,防止复制/拷贝时不必要的类型转换,在定义对象时必须显示调用初始化式,不能使用赋值操作符进行隐式转换。注:此代码未包含自定义删除器
成员函数:
(1)get函数:获取内部对象的指针,由于已经重载了()方法,因此和直接使用对象是一样的。
(2)release函数:放弃内部对象的所有权,将内部指针置空,此指针需要手动释放。
(3)reset函数:销毁内部对象并接受新的对象的所有权。
(4)默认构造函数,函数参数为变量地址
(5)拷贝构造函数,函数参数为引用
(6)重载函数operator*
(7)重载函数operator->
(8)重载函数operator=
#ifndef UNIQUE_PTR_H
#define UNIQUE_PTR_H
template<typename T>
class _unique_ptr
{
public:
_unique_ptr(T* p = nullptr) :_ptr(p); //默认构造函数
_unique_ptr(_unique_ptr<T>& p) :_ptr(p._ptr); //拷贝构造函数
T& operator*();
T* operator->();
_unique_ptr<T>& operator=(_unique_ptr<T>& p); //赋值操作符重载
T* get();
T* release();
void reset(T* p);
private:
T * _ptr;
};
#endif
#include"unique_ptr.h"
template<typename T>
_unique_ptr<T>::_unique_ptr(T* p)
{
_ptr = p;
}
template<typename T>
_unique_ptr<T>::_unique_ptr(_unique_ptr<T>& p)
{
_ptr = p.release();
}
template<typename T>
T& _unique_ptr<T>::operator*()
{
return *(this->_ptr);
}
template<typename T>
T* _unique_ptr<T>::operator->()
{
return this->_ptr;
}
template<typename T>
_unique_ptr<T>& _unique_ptr<T>::operator=(_unique_ptr<T>& p)
{
if (p.get() != this->get())
{
delete _ptr;
}
_p