①不能使用同一个裸指针赋值,或使用同一个裸指针初始化多个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; }
原因:
存在右值引用的等号运算符,右值引用的拷贝构造,就可以,而普通对象不能放在右值引用的拷贝构造或者等号运算符中。
用来引用即将死亡的对象
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;//这行还会报错,所以右值引用并不是用来引用常量,而是临时对象 }
void text01() { int* p = new int(10); unique_ptr<int>u_p(p); if (u_p)//将指针放在if的括号内,并不会出错 { } }
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; };