2017-08-28 1 views
7

へのポインタを設定する動的に割り当てられた変数を削除:私はこのコード(<code>array = 0;</code>)の端部を理解することはできません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の値。

これはなぜですか?配列がOSに返された後は、値0を割り当てる必要はありません。

コード:ポインタがNULLに設定されているように、これが行われhttp://www.learncpp.com/cpp-tutorial/6-9a-dynamically-allocating-arrays/

+1

ダングリングポインタを持たないようにするために、有効なポインタ(ただしNULL)を配列に設定します。だから、後で 'array'をテストしてから使用することができます。ポインタが使用されなくなった場合は、実際には不要になります。 – Jarod42

+0

int *配列は、ポインタとして、オブジェクトの割り当てが解除されていても、指し示されたアドレスに関する情報を保持します。その空間はもはやそのポインタに属していないので、ランダムなデータにアクセスできないように0に設定します。 – metamorphling

+2

'std :: vector'を使うと、それらの手動メモリ管理を避けることができます。 – Jarod42

答えて

15

アレイがOSに戻った後、値を0に割り当てる必要はありませんか?

operator deleteによってメモリが解放(割り当て解除)されているため、必要ではありません。しかし、delete[]を使用した後に、コード内の別の場所(関数、ループなど)でポインタを使用する場合が考えられます。

delete[]ステートメントが(dangling pointer)と呼ばれた後、変数には以前の割り当てのアドレスが保持されます。そのアドレスにアクセスすると、メモリがもはやあなたのものではないので、undefined bahaviour (UB)が得られます。ほとんどの場合、プログラムがクラッシュします。無効なアドレスを表すアドレス0に対するポインタをチェックしている

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

:あなたのようなnull pointerチェックを行うことを避けるために

このチェックを可能にするには、C++ 11が使用できない場合は、ポインタをnullptrまたはNULLに設定します。 nullptrキーワードは、ポインタ型のように動作し、CのようにCのような形であるべきであるので、型の安全性を導入しますNULL。プリC++ 11では、NULLは整数0として定義されているので、C++ 11以降はnullptrのエイリアスです。事前C++ 11コンパイラのためにそれを使用するために、独自のnullptrを定義するに
はここを見て:How to define our own nullptr in c++98?


deleteまたはdelete[]についての興味深い事実は、nullptrにそれを使用しても安全であるということです。これは、点2のcppreference.comまたはSO answerに書かれています。

オペレータはptrがヌルポインタであるか、または以前のポインタでなければ、この関数の標準ライブラリの実装の動作が定義されていない[...] []

2) を削除し、削除operator new[](size_t)またはオペレータnew[](size_t, std::nothrow_t)の標準ライブラリ実装から取得したものです。

+3

はい、**あなたのデザインでポインタの再利用が必要な場合、ポインタが何か有効なものを指していないことを伝えるフラグが必要です。それはヌルポインタのためのものです。それは何かを削除した後に**自動的に使用されるべきではありません**。特に、割り当てられたブロックを削除してポインタをnullに設定するデストラクタを書くのは愚かですが、初心者のコードでよく見られます。 –

+1

@PeteBeckerなぜそれは愚かであろうか?再利用が後で導入される場合に備えて、削除後に常にポインタを無効にするのはよい方法でしょうか?欠点は何ですか? – Sossisos

+1

@Sossisos - それは**ばかげた**の理由は、デストラクタが実行された後にオブジェクト**が存在しないことと**再利用するポインタ**がないことです。欠点は、思考の代わりにスローガンでコードするようなコードを書いた人に見せかけることです。 –

3

(C++で、我々はnullptr prefferかNULLと0以降は、異なるものでもよいです)。

配列が削除された可能性があるため、この戦術は、ダングリングポインタの可能性を排除し、それはそれはNULLに設定だという意味ではありません。

ポインタをNULLであるかどうか(コードの後半)をチェックする危険性がありますが、それはNULLではないことがわかりますが、ポインタがアクセス可能であると誤って信じています未定義の動作を引き起こします。

+0

nullptrに設定する必要があります。 C++のnullptrでは、NULLと0は異なるものです –

+0

@ArtemyVysotsky良い点、答えが更新されました。 – gsamaras

8

ポインタがぶら下がるのを避けるために、ポインタはNULL(0)に設定されています(ポインタはもはや自分のものではない同じメモリを指しています)。ローカル変数の場合、関数が削除後も継続していない場合(その明白なポインタは再利用されないので)、それは有用ではありません。グローバル/メンバー候補の場合、バグを避けるための良い習慣。

既に削除されたポインタにアクセスすると、ランダムなメモリを上書き/読み込みすることがあります(クラッシュよりも危険です)。undefined behaviorが発生し、NULLにアクセスすると即座にクラッシュします。 NULLがよりintタイプで、あいまいな状況を解決する+安全を入力し改善しながら、そのポインタ型として定義されているので、あなたがnullptrを使用する必要がありますので

ポインタを二重に削除する場合は、nullptrで削除を使用しても何も起こりませんが、すでに削除された非nullポインタを削除すると、undefined behaviorが発生し、プログラムはクラッシュします。

には、この使用のためにSTLコンテナ(リソースを自ら解放する(RAII))またはsmart pointersがあるため、純粋なポインタを使用しないでください。

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

Re:「バグを避けるための良い習慣」 - バグを避けるためのベストプラクティスは、**デザイン**のコードを正しく作成し** **デザインを実装することです。誰かが不注意になった場合に備えてnull_justへのポインタを自動的に設定することは、バグを避けることではありません**。 **設計**と実装** **ポインタは何も指していないことを示すnullを使用するシステム。 –

1

そうでない場合、あなたは無効なアドレスを指してポインタかどうかを知ることができる方法がないので、あなたは、一般的に「無効なアドレス」、すなわちNULL0またはポインタ型nullptrとして知られている値に割り当てます。言い換えれば、delete[]あなたの配列があなたのポインタが "使用できない"メモリアドレスを指していることを "知らない"とき。

関連する問題