智慧型指標的作用有如同指標,但會記錄有多少個 shared_ptrs 共同指向乙個物件。這便是所謂的引用計數。一旦最後乙個這樣的指標被銷毀,也就是一旦某個物件的引用計數變為 0,這個物件會被自動刪除。
shared_ptr 的實現機制其實就是在拷貝構造時使用同乙份引用計數。
同乙個 shared_ptr 被多個執行緒 「讀」 是安全的,同乙個 shared_ptr 被多個執行緒 「寫」 是不安全的。
比如說,用智慧型指標來建立乙個動態分配的字串物件:
// 新建立乙個物件,引用計數器為 1
shared_ptr
pstr(new
string("abc"));
解引用乙個智慧型指標返回它指向的物件。同樣,我們可以像操作普通指標一樣呼叫 string 提供的方法。
if (pstr && pstr->empty())
當有另外乙個智慧型指針對當前智慧型指標進行拷貝時,引用計數器加 1:
shared_ptr
pstr(new
string("abc")); // pstr 指向的物件只有乙個引用者
shared_ptr
pstr2(pstr); // pstr 跟 pstr2 指向相同的物件,此物件有兩個引用者
當兩個智慧型指標進行賦值操作時,左邊的指標指向的物件引用計數減 1,右邊的加 1。
shared_ptr
pstr(new
string("abc"));
shared_ptr
pstr2(new
string("hello"));
// 給 pstr2 賦值,令他指向另乙個位址,遞增 pstr 指向的物件的引用計數,遞減 pstr2 原來指向的物件引用計數
pstr2 = pstr;
指標離開作用域範圍時,同樣引用計數減1。當引用計數為0時,物件被**。
template class smart_ptrs
;
跟標準庫一樣,我們使用模板來實現它。
用普通指標進行初始化時,需要將該指標進行封裝,並且引用計數初始化為1。
template
smart_ptrs::smart_ptrs(t *p): count(new
int(1)), p(p)
定義拷貝建構函式:
template // 對普通指標進行拷貝,同時引用計數器加 1,因為需要對引數進行修改,所以沒有將引數宣告為 const
smart_ptrs::smart_ptrs(smart_ptrs &sp): count(&(++*sp.count)), p(sp.p)
定義指標運算子:
template t>
t* smart_ptrs:
:operator->()
定**引用運算子,直接返回底層指標的引用:
template t>
t& smart_ptrs::operator*()
定義賦值運算子,左邊的指標計數減 1,右邊指標計數加 1,當左邊指標計數為 0 時,釋放記憶體:
template smart_ptrs& smart_ptrs::operator=(smart_ptrs& sp)
this->p = sp.p;
this->count = sp.count;
return *this;
}
定義析構函式:
template
smart_ptrs::~smart_ptrs()
}
大功告成!
後面是個小測試:
#include
using
namespace
std;
template
class smart_ptrs
;// 定義建構函式
template
smart_ptrs::smart_ptrs(t *p): count(new
int(1)), p(p)
// 定義拷貝建構函式
template
// 對普通指標進行拷貝,同時引用計數器加 1,因為需要對引數進行修改,所以沒有將引數宣告為 const
smart_ptrs::smart_ptrs(smart_ptrs &sp): count(&(++*sp.count)), p(sp.p)
// 定義指標運算子
template
t* smart_ptrs::operator->()
// 定**引用運算子,直接返回底層指標的引用
template
t& smart_ptrs::operator*()
// 定義賦值運算子,左邊的指標計數減 1,右邊指標計數加 1,當左邊指標計數為 0 時,釋放記憶體
template
smart_ptrs& smart_ptrs::operator=(smart_ptrs& sp)
this->p = sp.p;
this->count = sp.count;
return *this;
}// 定義析構函式
template
smart_ptrs::~smart_ptrs()
}// test
int main()
直接用 gdb 看每一步的輸出結果就 ok 了:
p *pstr.count
p *pstr.p
四句話的輸出分別是:
1
"abc"
2"abc"
2"abc"
3"abc"
乙個簡單的Matrix實現
我們直接來看 吧 matrix.h pragma once include using namespace std 矩陣類 class matrix 下面是實現和測試的 matrix.cpp include matrix.h include include matrix matrix void ma...
LinkList的乙個簡單實現
鏈式線性表是資料結構裡很簡單但也是很常見的資料結構,相比順序儲存的線性表,可以更快的實現新增和刪除操作,但讀取速度比順序結構會慢。鏈式線性表的關鍵在於,每個資料儲存為節點形式。不僅僅儲存有資料,還有乙個引用 next 指向下乙個節點。鏈式結構還可以再擴充套件為雙向鍊錶 迴圈鍊錶等等。基本原理一樣,只...
實現乙個簡單的LinkedList
今天把jdk1.8的linkedlist原始碼看了一下,發現使用的資料結構就是雙向鍊錶。自己也動手實現了乙個簡易版本的雙向鍊錶 package com.natsuki.lesson2 author date 2018 12 29 description 自己根據雙向鍊錶定義乙個簡易linkedlis...