2017-08-28 32 views
7

我無法理解此代碼的末尾(array = 0;):刪除動態分配的變量設定指針爲0

#include <iostream> 

int main() 
{ 
    std::cout << "Enter a positive integer: "; 
    int length; 
    std::cin >> length; 

    int *array = new int[length]; 

    std::cout << "I just allocated an array of integers of length " << length << '\n'; 

    array[0] = 5; // set element 0 to value 5 

    delete[] array; // use array delete to deallocate array 
    array = 0; // use nullptr instead of 0 in C++11 

    return 0; 
} 

在結束時,動態分配的數組被刪除(返回到OS),然後分配值爲0.

爲什麼這樣做?數組返回到操作系統後,沒有必要爲它賦值0,對吧?從

代碼:http://www.learncpp.com/cpp-tutorial/6-9a-dynamically-allocating-arrays/

+1

它設置一個有效的(但爲空)指向數組的指針,以避免有懸掛指針。所以稍後,我們可以在使用之前測試'array'。如果指針不再使用,則確實不需要。 – Jarod42

+0

int *數組作爲一個指針,即使解除了對象的分配,仍然保留它指向的地址的信息。由於該空間不再屬於該指針,因此將其設置爲0,以便您不能訪問某些隨機數據。 – metamorphling

+2

使用'std :: vector'可以避免那些手動的內存管理。 – Jarod42

回答

15

將數組返回給操作系統後,不需要爲它賦值0,對不對?

你說得對,因爲內存被釋放(釋放)了operator delete。但想一想在你使用delete[]之後,你可以在你的代碼的另一個地方(函數,循環等)使用指針的情況。

array變量在delete[]聲明被稱爲(dangling pointer)後仍然保留舊分配的地址。如果你要訪問該地址,你會得到undefined bahaviour (UB),因爲內存不再是你的,在大多數情況下你的程序會崩潰。

爲避免你做一個null pointer檢查,如:

if (array != nullptr) 
{ 
    /* access array */ 
    ... 
} 

這是檢查,對代表的無效地址地址0的指針。

要使檢查成爲可能,請將指針設置爲nullptrNULL如果C++ 11不可用。 nullptr關鍵字引入了類型安全性,因爲它的行爲類似於指針類型,應該優於類似C的NULL。在pre C++ 11中NULL被定義爲整數0,因爲C++ 11它是nullptr的別名。
要定義自己nullptr使用它的前C++編譯器11看這裏:How to define our own nullptr in c++98?


一個有趣的事實有關deletedelete[]的是,它是安全的使用上nullptr。它寫在cppreference.com的第2點或這個SO answer

操作者刪除,操作者刪除[]

2) [...]的標準庫實現此功能的行爲是不確定的,除非ptr是空指針或在先前的指針從標準庫實現operator new[](size_t)或運營商new[](size_t, std::nothrow_t)獲得。

+3

是的,**如果你的設計需要重用指針,那麼你需要一個標誌來告訴你指針不指向有效的東西;這是一個空指針的用途。它應該**不會**在刪除之後自動使用。特別是,編寫一個析構函數是愚蠢的,它會刪除一個已分配的塊,然後將指針設置爲null,但這在初學者的代碼中經常出現。 –

+1

@PeteBecker爲什麼會這麼傻?在以後使用重複使用的情況下,是否總是在刪除後清空指針?缺點是什麼? – Sossisos

+1

@Sossisos - 這是**愚蠢**的原因是,析構函數運行後,對象**不存在**,並且**沒有指針**可重用。缺點是它使得編寫代碼的人看起來像是用口號代碼而不是思考。 –

3

這樣做,使得指針被設置爲NULL(無論是在C++中,我們preffer nullptr,由於NULL和0可以是不同的東西)。

這種策略消除了懸掛指針的可能性,因爲該數組可能已被刪除,但這並不意味着它被設置爲NULL

如果我們不這樣做,我們冒着檢查指針是否爲NULL的風險(在我們的代碼中後者),我們將看到它不是NULL,錯誤地認爲指針可以被訪問,並導致未定義的行爲。

+0

它應該設置爲nullptr。在C++ nullptr中,NULL和0是不同的東西 –

+0

@ArtemyVysotsky好點,回答更新。 – gsamaras

8

我們正在設置指針NULL(0)以避免懸掛指針(指針仍然指向不再是你的同一內存)。在局部變量的情況下,如果函數在刪除後不繼續,那麼它就沒有用處(所以它的明顯指針將不會被重用)。如果全球/會員poitners避免錯誤的良好做法。

訪問已經刪除的指針可能會導致覆蓋/讀取隨機內存(它可能比崩潰更危險),並導致undefined behavior,而訪問NULL指針將立即崩潰。

由於你應該使用nullptr,因爲它定義爲指針類型,而NULLint型和改善型安全+解析模糊的情況。

在雙刪除指針的情況下,其安全使用nullptr上的刪除並沒有任何反應,但如果刪除已刪除的非空指針,將導致undefined behavior,最有可能的程序將崩潰。

你應該避免使用純指針,因爲STL容器(這可以釋放它們自己的資源(RAII))或smart pointers

std::vector<int> array{1,2,3,4,5}; 
+1

回覆:「避免錯誤的良好做法」 - 避免錯誤的最佳做法是**設計**代碼並**實施**設計。自動設置指針爲空_just,以防有人不小心做**不**避免bug; **設計**和**實現**使用null來表示指針指向無效的系統。 –

1

分配給俗稱「無效地址」,即NULL0或指針類型nullptr的值,否則沒有辦法,你可以知道你是否指針指向的地址無效。換句話說,當你的數組delete[]你的數組指針「不知道」它指向一個不再可用的內存地址。