2016-06-18 2 views
0

これで2つのプログラムをレイアウトします。両方ともポインタと新しい演算子を使用する動的配列です。しかし、削除演算子が好きではないようです。C++ポインタと動的配列と削除演算子

#include <iostream> 
int main() 
{ 
    int *p; 
    p = new int[5]; 

    for (int i = 0; i < 5; i++) 
    { 
    p[i] = 25 + (i * 10); 
    std::cout << p[i] << " "; 
    } 
    std::cout << std::endl; 

    delete [] p; 
    p = NULL; 

    return 0; 
} 

これは最初のプログラムです。それは、削除演算子がうまく好きです。削除オペレータが嫌いなプログラム:

#include <iostream> 
int main() 
{ 
    int x; 
    int *p; 
    p = new int[5]; 

    *p = 4; 

    for (int i = 0; i < 5; i++) 
    { 
    std::cout << *p << " "; 
    x = *p; 
    p++; 
    *p = x + 1; 
    } 
    std::cout << std::endl; 

    delete [] p; 
    p = NULL; 

    return 0; 
} 

このプログラムはうまくコンパイルされます。しかし、実行中に、それはエラー - free(): invalid pointer: 0xfdb038 ..またはその特定の実行のためのメモリアドレスが何であれ、スローされます。したがって、質問は次のようになります。 2番目のケースでdelete演算子を使用できないのはなぜですか? 私はメモリリークを望んでいません。私はポインタがぶら下がっていることを望んでいません。 私はちょうどp = NULL;と言うならば、p = 0が、まだ私はポインタがまだぶら下がっていると信じていますか?しかし、わかりません。前もって感謝します。コードの2番目の部分で、このループで

+2

2番目のケースでは、 'p'ポインタを変更するため、削除前に配列の先頭に移動しないためです。 –

答えて

2

ルック:この行では、あなたが現在pが指すメモリアドレスに書き込むこと

for (int i = 0; i < 5; i++) 
{ 
    std::cout << *p << " "; 
    x = *p; 
    p++; 
    *p = x + 1; // <--- Here 
} 

注意してください。あなたはいつもpをインクリメントして書き込むので、pのために割り当てた領域の終わりを過ぎて書くことになります。 (もしpOrigがが最初に指し示す場所へのポインタとして想像すれば、これはpOrig[1],pOrig[2],pOrig[3],pOrig[4]およびpOrig[5]に書き込み、最後の書き込みは領域の最後を過ぎている)。この結果、未定義の動作になります。つまり、文字通り何かが起こる可能性があります。これは悪いニュースです。

さらに、delete[]は、割り当てた配列の最初の要素へのポインタを渡していることを前提としています。そのループでpを何度もインクリメントしてきたので、delete[]には、割り当てられた配列の基底にないポインタがあります。そのため、問題です。

これを修正するには、増分後にpに書き込まず、new[]で割り当てられた元の配列にポインタを格納して、変更されたポインタpではなくそのポインタを解放できるようにします。

0

あなたは、から得たポインタをnewにする必要があります。しかし、2番目のコードでは、ポインタを変更したp++を実行しました。したがってnewdeleteから取得しなかったポインタをdeleteにしようとしました。

このタイプのエラーを修正するには、newを使用しないでください。代わりにstd::vector<int> p;を使用してください。 newは決して必要ないので、deleteを忘れることはできません。

+2

"このタイプのエラーを修正するには新しい"を使用しないでください - 何か奇妙なアドバイス... –

+3

@EdgarRokyanどのように奇妙ですか?現代のC++では、手動でのメモリ管理を見つけることはできません。このエラーを起こしやすい、時代遅れの、不要なプラクティスに身を任せる必要はありません。 – nwp

+0

@EdgarRokyan現代のC++では、明示的な 'new'と' delete'演算子を避ける傾向があります。たとえば、 'make_shared'と' make_unique'をスマートポインタ型と組み合わせて見てください。 – templatetypedef

0

pp++に変更されています。 元のポインタを保存する(削除する)必要があります。このように:

#include <iostream> 
int main() 
{ 
    int *original = new int[5]; 
    int *p = original; 

    for (int i = 0; i < 5; i++) 
    { 
    std::cout << *p << " "; 
    int x = *p; 
    p++; 
    *p = x + 1; 
    } 
    std::cout << std::endl; 

    delete [] original;  
    return 0; 
}