C 智慧型指標

2021-09-25 16:38:24 字數 4380 閱讀 1535

首先要知道智慧型指標是用來解決什麼問題的,首先我們先看下面這段**

void func(int *p)

delete sp;

}

這個函式有乙個很大的問題,如果傳入的引數p為空,遇到 if 語句就命中之後就會丟擲異常,程式中斷。那麼指標sp指向開闢的記憶體沒有釋放,導致記憶體洩漏。有什麼方法可以來解決這個問題?

棧:系統開闢記憶體,系統釋放;堆:手動開闢記憶體,手動釋放。那麼如果能對堆上空間實現使用者分配、系統自行**的機制,就不用擔心記憶體洩露的問題了。

智慧型指標的思想:定義乙個類來封裝資源的分配和釋放,在建構函式完成資源的分配和初始化,在析構函式中完成資源的清理和釋放,可以保證資源的正確使用和釋放。(資源指的是堆上資源)

看下面這段**:

#includetemplate class smart_ptr

~smart_ptr()//析構函式

t& operator*()//*運算子過載

t* operator->()//->運算子過載

private:

t *mptr;

};int main()

smart_ptrsp2 = sp1;這句**會釋放同一塊記憶體兩次,導致程式出錯。

這裡介紹四個智慧型指標auto_ptr

1、auto_ptr(已經被摒棄

實現一:不帶標記的auto_ptr(所有權唯一)

smart_ptr(const smart_ptr& rhs)//拷貝建構函式

smart_ptr& operator=(const smart_ptr& rhs)//賦值運算子過載

return *this;

} t& operator*()

t* operator->()

private:

void release()const

t *mptr;

};int main()

問題:*sp1 = 20; sp1指標指向已經為null,對其解引用訪問了保留區的資料,程式出錯。

實現二:帶有標記的auto_ptr(釋放權唯一,管理權不唯一),即可以多個auto_ptr管理同一片記憶體,但是只能有乙個指標釋放該片記憶體。怎麼確定是哪個指標能釋放呢?在成員變數中加入乙個標誌變數flag,flag為true則有釋放權,flag為false則沒有釋放權。那麼就牽扯釋放許可權轉移的問題,概括來說就是舊智慧型指標擁有的許可權,那麼新智慧型指標也擁有。舊智慧型指標沒有的許可權,那麼新智慧型指標也沒有。

這個功能的實現:new flag = old flag;   old flag = false;

#includetemplateclass smartptr

smartptr(const smartptr& rhs) :mptr(rhs.mptr)

smartptr& operator = (const smartptr& rhs)

return *this;

} ~smartptr()

mptr = null;

} t& operator*()

t* operator->()

private:

t* mptr;

mutable bool flag;//是否擁有釋放權

};void func(smartptrsp)//true

{}int main()

問題:根據管理權原則一,若舊智慧型指標有釋放權,則新智慧型指標將釋放權拿走,舊釋放權false。那麼如果這個新智慧型指標只是乙個臨時量,隨著生存週期的到來也隨之消失,那塊被管理的記憶體豈不是莫名其妙就被釋放了

2、scope_ptr(管理權唯一,釋放權唯一)在auto_ptr中,因為設計的問題,導致在使用拷貝建構函式和 賦值運算子的可過載函式時,發生了訪問 空指標、野指標的情況。為了規避這些情況,scoped_str在設計的時候就直接遮蔽了 拷貝建構函式 和 賦值運算子過載函式。

#includetemplateclass scope_ptr

~scope_ptr()

t& operator*()

t* operator->()

private:

scope_ptr(const scope_ptr&);

scope_ptr& operator=(const scope_ptr&);

t* mptr;

};int main()

問題: scoped_ptr的原則也是「管理權唯一,釋放權唯一」,因為遮蔽了 拷貝建構函式 和 賦值運算子過載函式,所以不可能通過這兩種方式去 使得兩個及以上的指標指向同一片記憶體,但是仍然避免不了人為的操作,如sp1和sp2;即初始化兩個scope_ptr指向同一片記憶體,當其中乙個指標釋放了該記憶體,另乙個再想去修改記憶體的內容的話程式就會崩潰

3、shared_ptr(管理權不唯一,釋放權不唯一)

shared_ptr是基於「引用計數」實現的,多個shared_ptr可指向同一片記憶體,並且它們維護著共享的引用計數器——記錄著指向同一片記憶體的shared_ptr物件的個數。當最後乙個指向某一片記憶體的shared_ptr物件也銷毀之後,會自動銷毀掉該片記憶體。shared_ptr很好地解決了 多個智慧型指標指向一塊記憶體塊時, 析構時程式崩潰 的情況。

引用計數器:我們只需要乙個 引用計數器物件,這個物件中就儲存了所有關於記憶體引用的資訊。

}void delref(void* mptr)//刪除

else

}} int getref(void* mptr)//獲取

else

}private:

class node;

std::vector::iterator find(void* mptr)//使用迭代器查詢

}return it;

} class node//結點型別

//建構函式

public:

void* addr;//存放的位址

int ref;//引用計數

}; std::vectorvec;

};

templateclass shared_ptr

shared_ptr(const shared_ptr& rhs) :mptr(rhs.mptr)//拷貝建構函式

shared_ptr& operator = (const shared_ptr& rhs)//賦值運算子過載

mptr = rhs.mptr;

addref();

} return *this;

} ~shared_ptr()

mptr = null;

} t& operator*()

t* operator->()

private:

void addref()

void delref()

int getref()

t* mptr;

static ref_management rm;//引用計數器成員變數象

};//靜態成員變數類外初始化

templateref_management shared_ptr::rm;

int main()

問題:雖然shared_ptr很好地解決了 「多個智慧型指標指向同一塊記憶體時,析構時出錯」的問題,可是同時也帶來了新的問題。shared_ptr之間不能相互引用,否則管理的堆上記憶體塊無法釋放。

c 智慧型指標

auto prt 它是 它所指向物件的擁有者 所以當自身物件被摧毀時候,該物件也將遭受摧毀,要求乙個物件只有乙個擁有者,注意 auto prt 不能使用new 來分配物件給他 include include using namespace std template void bad print au...

c 智慧型指標

很久沒寫部落格了,不知道如何表達了,哈哈.我先介紹一下深淺拷貝.class copy 此時a.ptr和b.ptr指向同乙個物件,當我們delete a.ptr時 b.ptr所指向的物件已經不存在了,要是我們引用b.ptr指向的物件也就會出問題了.深拷貝 把a.ptr所指向的物件拷貝乙份給b.ptr ...

c 智慧型指標

記得前不久有一次面試被問到智慧型指標的實現,當時對智慧型指標只是聽說但沒有了解過,就亂七八糟地說了一遍。今天寫了一遍智慧型指標,用了引用計數的概念。主要思想就是,用乙個新類對原本需要的型別進行了一層封裝,這個新類中儲存了原本的物件指標和乙個引用計數的指標,之所以全部用指標來儲存,就是因為會出現多個新...