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>。