Boost庫基礎-智能指針(shared_ptr)

shared_ptr

shared_ptr與scoped_ptr同樣是用於管理new動態分配對象的智能指針,它們都重載了 *和->操作符,提供顯示bool類型轉換以判斷指針的有效性,get()可以得到原始指針,並且沒有提供指針算術操作,也不能管理new[ ] 產生的動態數組指針。

例:

shared_ptr<int> spi(new int);

//解引用
*spi = 222;

//一個string的shared_ptr
shared_ptr<string> sps(new string("smart")); 

//獲取大小
sps->size();

//危險,不能正確釋放內存
shared_ptr<int> s(new int[10]); 

特點:它是可以被安全共享的——shared_ptr是一個“全功能”的類,有着正常的拷貝、賦值語義,也可以進行shared_ptr間的比較,是 “最智能” 的智能指針。

成員函數:

①無參數的shared_ptr,創建一個持有空指針的shared_ptr。

②shared_ptr(Y *p) 獲得指向類型T的指針P的管理權,同時引用計數置爲1。這個構造函數要求Y類型必須能夠轉換爲T類型。

③shared_ptr(shared_ptr const& r)從另外一個shared_ptr獲得指針的管理權,同時引用計數加1,結果是兩個shared_ptr共享一個指針的管理權。

④operator=賦值操作符可以從另外一個shared_ptr獲得指針的管理權,其行爲同構造函數。

⑤reset()的作用是將引用計數減1,如果引用計數爲0,則刪除對象。

⑥use_count()返回當前的引用計數,僅僅用於測試或者調試,他不提供高效率操作,unique()則是可靠的,任何時候都可用。

⑦shared_ptr支持比較運算,a.get() == b.get()。它還可以使用operator < 比較大小,這使得它可以用於(set和map)。

⑧支持operator << 運算符,輸出內部指針值,方便調試。

typedef shared_ptr<string> sp_t;

map<sp_t,int> m;

sp_t sp(new string("one"));
m[sp] = 111;

用法:

#include <iostream>
#include <string>
#include <boost/smart_ptr.hpp>

using namespace std;
using namespace boost;

int main()
{
	//創建對象
	boost::shared_ptr<int> sp(new int(10));

	//判斷是否是唯一
	assert(sp.unique());

	//第二個shared_ptr,調用拷貝構造
	boost::shared_ptr<int> sp2 = sp;

	//判斷是否相等,並且引用計數爲2
	assert(sp == sp2 && sp.use_count() == 2);

	//使用解引用操作符修改被指對象
	*sp2 = 100;

	//判斷另外一個是否也同時被修改
	assert(*sp == 100);

	//停止shared_ptr的使用
	sp.reset();

	getchar();
	return 0;
}

以下爲shared_ptr應用於標準容器的用法:

#include <iostream>
#include <string>
#include <vector>
#include <boost/smart_ptr.hpp>
#include <boost/make_shared.hpp>

using namespace std;
using namespace boost;

int main()
{
	typedef vector<boost::shared_ptr<int>> vs;
	
	vs v(10);

	//兩種賦值方式
	int i = 0;
	//for (auto pos = v.begin(); pos != v.end(); ++pos)
	//{
	//	//賦值
	//	(*pos) = boost::make_shared<int>(++i);
	//	cout << *(*pos) << ", ";
	//}
	for (auto &ptr : v)
	{
		ptr = boost::make_shared<int>(++i);
		cout << *ptr << ", ";
	}

	cout << endl;

	boost::shared_ptr<int> p = v[9];
	*p = 100;

	cout << *v[9] << endl;

	getchar();
	return 0;
}

定製刪除器:

它擁有這個構造函數 shared_ptr(Y *p, D d)。

第一個參數與其他構造函數參數相同。第二個刪除器參數d則告訴shared-ptr在析構時不是使用delete來操作指針p,而是用d來操作,即把 delete p 換成 d(p);

//假設有一組操作socket的函數,使用一個socket_t類
class socket_t {...};

//打開socket
socket_t *open()
{
    cout<<"open socket"<<endl;
    return new socket_t;
}

//關閉socket
socket_t *close()
{
    cout<<"close socket"<<endl;
    return new socket_t;
}


socket_t *s = open();

//傳入刪除器
shared_ptr<socket_t > p(s,close);

shared_ptr<void>

shared_ptr<void>能夠存儲void*類型的指針,而void*類型指針可以指向任意類型,因此shared_ptr<void>就像是一個泛型的指針容器,擁有容納任意類型的能力,如果存儲爲void*型指針,爲了在需要的時候正確使用,可以使用static_pointer_cast<T>等轉型函數重新轉爲原來的指針,但它會使代碼不夠安全,建議不要這樣使用。

別名構造函數

//一種比較特殊的構造函數
template<class Y>
shared_ptr(shared_ptr<Y> const &r,element_type *p)

它的作用是共享r的引用計數,但實際持有的卻是另外一個可能毫無關係的指針p。而且並不負責p的自動銷燬。一個使用例子

//一個pair的智能指針
auto p1 = make_shared<std::pair<int,int>>(0,1)

//別名構造
shared_ptr<int> p2(p1,&p1->second);

//原引用計數加1
assert(p1.use_count() == 2);

//兩者引用計數相同
assert(p1.use_count() == p2.use_count());

//但指向的內容不同
assert((void *)p1.get() != (void*)p2.get());

//指向的是另外的指針
assert(&p1->second == p2.get())

 shared_array

它的接口與功能與shared_ptr是相同的,主要區別:

①構造函數接受的指針是new[ ] 的結果

②提供operator[ ] 操作符重載

③沒有 *、->操作符重載,因爲它持有的不是一個普通指針

④析構函數使用delete[ ] 釋放資源,而不是delete

用法:

#include <iostream>
#include <string>
#include <vector>
#include <boost/smart_ptr.hpp>
#include <boost/make_shared.hpp>

using namespace std;
using namespace boost;

int main()
{
	int *p = new int[100];
	shared_array<int> sa(p);

	shared_array<int> sa2 = sa;

	sa[0] = 10;

	getchar();
	return 0;
}

shared_array能力有限,多數情況下使用shared_ptr<std::vector>或者std::vector<shared_ptr>。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章