C++ 智能指針

使用智能指針的緣由
  1. 考慮下邊的簡單代碼:

    int main()
    {
    int *ptr = new int(0);
    return 0;
    }
      就如上邊程序,我們有可能一不小心就忘了釋放掉已不再使用的內存,從而導致資源泄漏(resoure leak,在這裏也就是內存泄漏)。

2. 考慮另一簡單代碼:

int main()
{
int *ptr = new int(0);
delete ptr;
return 0;
}
  我們可能會心想,這下程序應該沒問題了?可實際上程序還是有問題。上邊程序雖然最後釋放了申請的內存,但ptr會變成空懸指針(dangling pointer,也就是野指針)。空懸指針不同於空指針(nullptr),它會指向“垃圾”內存,給程序帶去諸多隱患(如我們無法用if語句來判斷野指針)。

上述程序在我們釋放完內存後要將ptr置爲空,即:

1 ptr = nullptr;
  除了上邊考慮到的兩個問題,上邊程序還存在另一問題:如果內存申請不成功,new會拋出異常,而我們卻什麼都沒有做!所以對這程序我們還得繼續改進(也可用try…catch…):

複製代碼
1 #include
2 using namespace std;
3
4 int main()
5 {
6 int *ptr = new(nothrow) int(0);
7 if(!ptr)
8 {
9 cout << “new fails.”
10 return 0;
11 }
12 delete ptr;
13 ptr = nullptr;
14 return 0;
15 }
複製代碼
  3. 考慮最後一簡單代碼:

複製代碼
1 #include
2 using namespace std;
3
4 int main()
5 {
6 int *ptr = new(nothrow) int(0);
7 if(!ptr)
8 {
9 cout << “new fails.”
10 return 0;
11 }
12 // 假定hasException函數原型是 bool hasException()
13 if (hasException())
14 throw exception();
15
16 delete ptr;
17 ptr = nullptr;
18 return 0;
19 }
複製代碼
  當我們的程序運行到“if(hasException())”處且“hasException()”爲真,那程序將會拋出一個異常,最終導致程序終止,而已申請的內存並沒有釋放掉。

當然,我們可以在“hasException()”爲真時釋放內存:

複製代碼
// 假定hasException函數原型是 bool hasException()
if (hasException())
{
delete ptr;
ptr = nullptr;
throw exception();
}

#include<iostream>
#include<vector>
#include<math.h>
using namespace std;

void func(int *ptr)
{
	int *p = new int;//auto_ptr<int> p(new int)
	if(ptr == NULL)
	{
		throw exception("ptr is null");
	}

	*p = *ptr;//這兩句代碼不執行,出現了內存泄漏
	delete p;
}

int main()
{
	func(NULL);
	return 0;
}

但,我們並不總會想到這麼做。而且,這樣子做也顯得麻煩,不夠人性化。
如果,我們使用智能指針,上邊的問題我們都不用再考慮,因爲它都已經幫我們考慮到了。

因此,我們使用智能指針的原因至少有以下三點:

1)智能指針能夠幫助我們處理資源泄露問題;

2)它也能夠幫我們處理空懸指針的問題;

3)它還能夠幫我們處理比較隱晦的由異常造成的資源泄露。

boost智能指針
C++11之前只有一個auto_ptr
C++11之後unique_ptr、shared_ptr、weak_ptr

  1. 智能指針auto_ptr的引入

auto_ptr是C++標準庫中的智能指針模板類,頭文件
auto_ptr的出現,主要是爲了解決“有異常拋出時發生內存泄漏”的問題。

unique_ptr

unique_ptr是C++標準庫自C++11起開始提供的類型。它是一種在異常發生時可幫助避免資源泄露的智能指針。一般而言,這個智能指針實現了獨佔式擁有概念,意味着它可確保一個對象和其相應資源同一時間只被一個指針擁有。一旦擁有者被銷燬或變成空,或開始擁有另一個對象,先前擁有的那個對象就會被銷燬,其任何相應資源也會被釋放。

shared_ptr

幾乎每一個有分量的程序都需要“在相同時間的多處地點處理或使用對象”的能力。爲此,我們必須在程序的多個地點指向(refer to)同一對象。雖然C++語言提供引用(reference)和指針(pointer),還是不夠,因爲我們往往必須確保當“指向對象”的最末一個引用被刪除時該對象本身也被刪除,畢竟對象被刪除時析構函數可以要求某些操作,例如釋放內存或歸還資源等等。

所以我們需要“當對象再也不被使用時就被清理”的語義。Class shared_ptr提供了這樣的共享式擁有語義。也就是說,多個shared_ptr可以共享(或說擁有)同一對象。對象的最末一個擁有者有責任銷燬對象,並清理與該對象相關的所有資源。

shared_ptr的目標就是,在其所指向的對象不再被使用之後(而非之前),自動釋放與對象相關的資源。

     weak_ptr 是一種不控制對象生命週期的智能指針, 它指向一個 shared_ptr 管理的對象. 進行該對象的內存管理的是那個強引用的 shared_ptr. weak_ptr只是提供了對管理對象的一個訪問手段. 

weak_ptr 設計的目的是爲配合 shared_ptr 而引入的一種智能指針來協助 shared_ptr 工作, 它只可以從一個 shared_ptr 或另一個 weak_ptr 對象構造, 它的構造和析構不會引起引用記數的增加或減少.

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