天天看點

C++智能指針(2)—— unique_ptr1、unique_ptr2、右值引用3、bool類型的重載4、自己重寫部分源碼

C++智能指針(2)—— unique_ptr

  • 1、unique_ptr
  • 2、右值引用
  • 3、bool類型的重載
  • 4、自己重寫部分源碼

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;
}
           
C++智能指針(2)—— unique_ptr1、unique_ptr2、右值引用3、bool類型的重載4、自己重寫部分源碼

原因:

存在右值引用的等号運算符,右值引用的拷貝構造,就可以,而普通對象不能放在右值引用的拷貝構造或者等号運算符中。

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;
};