C++智能指针(2)—— unique_ptr
1、unique_ptr
①不能使用同一个裸指针赋值,或使用同一个裸指针初始化多个unique ptr
②不允许隐式构造
void text01()
{
int* p = new int(10);
unique_ptr<int> u_p=p;//报错,不允许隐式构造
unique_ptr<int> u_p1(p);
cout << *p << endl;
cout << u_p << endl;
}
int main()
{
text01();
return 0;
}
③不允许拷贝构造,不允许等号运算符重载
void text01()
{
int* p = new int(10);
unique_ptr<int> u_p(p);
unique_ptr<int> u_p1(p);
u_p1 = u_p;//不允许等号运算符重载,会报错
cout << *p << endl;
cout << u_p << endl;
}
int main()
{
text01();
return 0;
}
但是为什么下面的程序却能够通过?
unique_ptr<int> fun(unique_ptr<int>& ptr)
{
cout << *ptr << endl;
int* p = new int(9);
return unique_ptr<int>(p);
}
void text01()
{
int* p = new int(10);
unique_ptr<int>u_p(p);
unique_ptr<int>u_p2(fun(u_p));//有拷贝构造的过程,但是能够运行通过
cout << *u_p2 << endl;
}
int main()
{
text01();
return 0;
}
原因:
存在右值引用的等号运算符,右值引用的拷贝构造,就可以,而普通对象不能放在右值引用的拷贝构造或者等号运算符中。
2、右值引用
用来引用即将死亡的对象
void text02()
{
const int& a = 10;
int&& b = 10;
//上面两行等价,如果只是int& a = 10,会报错,原因是a是一个不可取地址的量,10会产生临时量,具有常属性,所以对a前面加上const
const int c = 10;
const int& d = c;
int&& e = c;//这行还会报错,所以右值引用并不是用来引用常量,而是临时对象
}
3、bool类型的重载
void text01()
{
int* p = new int(10);
unique_ptr<int>u_p(p);
if (u_p)//将指针放在if的括号内,并不会出错
{
}
}
4、自己重写部分源码
template <typename T>
class Munique_ptr
{
public:
//构造
explicit Munique_ptr(T* ptr = nullptr)
:_ptr(ptr)//explicit用来防止隐式构造
{
}
//拷贝构造
Munique_ptr(Munique_ptr& src) = delete;
//等号运算符重载
Munique_ptr operator=(Munique_ptr& src) = delete;
//移动拷贝构造
Munique_ptr(Munique_ptr&& src)
:_ptr(src.release())
{
}
//移动等号运算符重载
Munique_ptr operator=(Munique_ptr&& src)
{
_ptr = src.release();
}
~Munique_ptr()
{
delete _ptr;
//unique_ptr的源码中有删除器,从而根据请款选择delete还是delete[],而本篇不妨写删除器部分
}
T* release()
{
T* tmp = _ptr;
_ptr = nullptr;
return tmp;
}
void reset()
{
delete _ptr;
_ptr = nullptr;
}
T& operator*()
{
return *_ptr;
}
T* operator->()
{
return _ptr;
}
operator bool()
{
return _ptr != NULL;
}
private:
T* _ptr;
};