垂懸指標,啞指標,野指標,智慧型指標

2021-10-04 12:08:02 字數 3391 閱讀 4314

定義:指標正常初始化,曾指向乙個物件,該物件被銷毀了,但是指標未製空,那麼就成了懸空指標。

解決策略:引入智慧型指標可以防止垂懸指標出現。一般是把指標封裝到乙個稱之為智慧型指標類中,這個類中另外還封裝了乙個使用計數器,對指標的複製等操作將導致該計數器的值加1,對指標的delete操作則會減1,值為0時,指標為null。

啞指標指傳統的c/c++指標,它只是乙個指向,除此以外它不會有其他任何動作,所有的細節必須程式設計師來處理,比如指標初始化,釋放等等

定義:指標指向了一塊隨機的空間,不受程式控制。訪問乙個已銷毀或者訪問受限的記憶體區域的指標,野指標不能判斷是否為null來避免

產生的原因:

指標定義時未被初始化:指標在被定義的時候,如果程式不對其進行初始化的話,它會隨機指向乙個區域,因為任意指標變數(出了static修飾的指標)它的預設值都是隨機的

指標被釋放時沒有置空:指標指向的記憶體空間在用free()和delete釋放後,如果程式設計師沒有對其進行置空或者其他賦值操作的話,就會成為乙個野指標.

#include #include #include #include using namespace std;

int main(void)

for(int i = 0; i < 5; i++) //i=5後為亂碼

cout<<*(p+i)<<" ";

cout<

指標操作超越變數作用域:不要返回指向棧記憶體的指標或者引用,因為棧內存在函式結束的時候會被釋放。class a};

class b

void test1(void)

};

注意:函式 test1 在執行語句 p->func()時,物件 a 已經消失,而 p 是指向 a 的,所以 p 就成了「野指標」

危害:指標指向的內容已經無效了,而指標沒有被置空,解引用乙個非空的無效指標是乙個未被定義的行為,也就是說不一定導致錯誤,野指標被定位到是**出現問題,在**指標就失效了,不好查詢錯誤的原因。

規避方法:

初始化指標的時候將其置為nullptr,之後對其操作。

釋放指標的時候將其置為nullptr。

更進一步地說,智慧型指標的出現是為了滿足管理類中指標成員的需要。包含指標成員的類需要特別注意複製控制和賦值操作,原因是複製指標時只複製指標中的位址,而不會複製指標指向的物件。當類的例項在析構的時候,可能會導致垂懸指標問題。

當類中有指標成員時,一般有兩種方式來管理指標成員:

一是採用值型的方式管理,每個類物件都保留乙份指標指向的物件的拷貝;

另一種更優雅的方式是使用智慧型指標,從而實現指標指向的物件的共享。它是指一種實現,能讓指標在離開自己生命週期的時候自動銷毀指向的內容(物件等),這往往用乙個物件將指標包裝起來來實現,例如標準庫中的auto_ptr和boost中的智慧型指標都是智慧型指標的例子,但是缺點就是沒有帶引用引數。

智慧型指標的一種通用實現技術是使用引用計數(reference count)。智慧型指標類將乙個計數器與類指向的物件相關聯,引用計數跟蹤該類有多少個物件共享同一指標。智慧型指標結合了棧的安全性和堆的靈活性,本質上將就是棧物件內部包裝乙個堆物件

每次建立類的新物件時,初始化指標並將引用計數置為1;當物件作為另一物件的副本而建立時,拷貝建構函式拷貝指標並增加與之相應的引用計數;對乙個物件進行賦值時,賦值操作符減少左運算元所指物件的引用計數(如果引用計數為減至0,則刪除物件),並增加右運算元所指物件的引用計數;呼叫析構函式時,析構函式減少引用計數(如果引用計數減至0,則刪除基礎物件)。

實現引用計數有兩種經典策略:一是引入輔助類,二是使用控制代碼類。

例如:

class testptr

~testptr()

// other operations

private:

int * ptr;

// other data

};

在程式中,類testptr物件的任何拷貝、賦值操作都會使多個testptr物件共享相同的指標。但在乙個物件發生析構時,指標指向的物件將被釋放,從而可能引起懸垂指標。

stl中auto_ptr只是眾多可能的智慧型指標之一,auto_ptr所做的事情,就是動態分配物件以及當物件不再需要時自動執行清理。

// 關於乙個智慧型指標的定義

templateclass auto_ptr

~auto_ptr()

private:

type *ptr;

};void processadoption(istream &data)

return;

}

注意事項:

auto_ptr不能共享所有權。

auto_ptr不能指向陣列

auto_ptr不能作為容器的成員。

不能通過賦值操作來初始化auto_ptr

std::auto_ptr p(new int(42)); //ok

std::auto_ptr p = new int(42); //error

這是因為auto_ptr 的建構函式被定義為了explicit

不要把auto_ptr放入容器

智慧型指標是儲存指向動態分配(堆)物件指標的類。除了能夠在適當的時間自動刪除指向的物件外,他們的工作機制很像c++的內建指標。智慧型指標在面對異常的時候格外有用,因為他們能夠確保正確的銷毀動態分配的物件。他們也可以用於跟蹤被多使用者共享的動態分配物件。

事實上,智慧型指標能夠做的還有很多事情,例如處理執行緒安全,提供寫時複製,確保協議,並且提供遠端互動服務。有能夠為這些esp (extremely smart pointers)建立一般智慧型指標的方法,但是並沒有涵蓋進來。

智慧型指標的大部分使用是用於生存期控制,階段控制。它們使用operator->和operator*來生成原始指標,這樣智慧型指標看上去就像乙個普通指標。

這樣的乙個類來自標準庫:std::auto_ptr。它是為解決資源所有權問題設計的,但是缺少對引用數和陣列的支援。並且,std::auto_ptr在被複製的時候會傳輸所有權。在大多數情況下,你需要更多的和/或者是不同的功能。這時就需要加入smart_ptr類。

在boost中的智慧型指標有:

垂懸指標問題

垂懸指標問題,這個問題的定義我是知道的。通常是說當指向某塊記憶體的指標被釋放之後,需要及時置空。否則,如果不置空,當下次不小心訪問到時,會導致錯誤。當然,這個問題說起來很簡單。覺得也沒什麼太大的問題,但是指標這一塊確實得非常小心,從下面我范的這個問題說起。下面這段 是我刷leetcode的時候的一段...

C 空懸指標 野指標

指向已經被釋放的記憶體 或者 指向已經被銷毀的物件。情況一 變數c釋放,dp變成空懸指標 情況二 void func 當free或者delete呼叫時,除了釋放動態申請的記憶體,還要將相關的指標指向null,避免出現空懸指標 情況三 int func void num是基於棧的變數,當func函式返...

空懸指標和野指標

以前經常把這兩個概念混為一談,雖然這它們的概念類似,有一定的相似性,但是各自的成因和解決防範方法都是不同的,特記錄在此。乙個原生指標分配記憶體後,它並沒有探測記憶體是否已經被釋放或者被損壞的能力。當所管理的記憶體被釋放後,若這個指標沒有被銷毀或置為null,它就成了乙個空懸指標。可能會出現隨機的錯誤...