實現乙個簡單的 shared ptr

2021-08-01 17:29:35 字數 2977 閱讀 3934

智慧型指標的作用有如同指標,但會記錄有多少個 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...