-3
#include <iostream>
#include <cstdio>
using namespace std;

int main(void)
{
    int arr[] = {1,4,2,3,5,6};
    int *p = arr;
    delete p;

    for(int i = 0 ; i < 6; i++)
        cout << p[i];

    return 0;
}

出力は142356です。delete pなぜこれがpを削除しないのですか?

コードを実行したときにセグメンテーション違反が発生することはありませんか?

4

4 に答える 4

5

中国の賢僧がかつて言ったように、「定義されていない動作は定義されていません」。

真剣に、ddeleteではない何かを試みることは未定義です。new

c と c++ はどちらも、予期しない機能の大部分を「未定義」として定義しています。これは、そのような行動をとると、何が起こるかわからないことを意味します。本当に運が良ければ、セグメント障害または同様のエラーが発生します。より通常、奇妙で不可解なことが起こり、それらについて推論しようとすることはほとんど無意味です.

これの主な理由は、コンパイラーの実装をより単純にし、より最適にするためです。

C++ プログラマーとして、Undefined Behaviour、Unspecified Behavior、Implementation Defined Behavoir を読むことをお勧めします。これらはすべて、ある程度興味深い C++ コードがどのように機能するかを理解するための基礎となります。

undefined behavoir に関するLLVM プロジェクトのブログはすばらしい読み物です。

于 2013-06-10T11:06:00.510 に答える
3

未定義の動作があります。

 int arr[] = {1,4,2,3,5,6};
 int *p = arr;
 delete p;

ここでarrは、動的に割り当てられずに作成されます。ポインターpでさえ動的に割り当てられません。その上ではご利用いただけませんdeletedelete[or delete[]] は、[or ] を使用newして割り当ててから、動的に割り当てられたメモリを解放するためにnew[]使用します。delete

ポインターを定義 (または宣言) しても、メモリーは割り当てられません。あなたが使うnew

int * p = new int;  //later deleted as delete p;

また

int * p = new int[5]; //later deleted as delete[] p;

メモリを割り当て、後で削除します。(また、 と の数はnew等しくdelete、コード内で対応している必要があります)

于 2013-06-10T11:21:17.847 に答える
1

「未定義の動作」を使用しています。この場合、解放後にポインターを使用します (そして、新しいものではないものを解放します) - C++ (C など) は高速になるように設計されています。したがって、オブジェクトを削除するときにメモリが何であるかをチェックしたり、メモリを何か他のもので埋めたりするなど、「不必要な」ことは行いません。単にそのメモリを「空き」としてマークし、後で何か他のものを割り当てるときに、そのメモリを新しい割り当てに使用します (または選択する可能性があります)。

単純な の代わりにクラスがある場合はint、デストラクタにクラスのメンバー変数に書き込み、クリアさせることができます。intしかし、long、 、 などの組み込み型についてはdouble、何も行われません。

undefinde 動作はまさに未定義であることに注意してください。それはあなたが期待する以外のことをすることができ、またそうするでしょう-しかし、あなたが期待することを完全に行うこともできます. その一部は、あなたが期待するものに依存します。要点は、何かを実行したときに何が起こるかについて標準が述べていないことです (たとえば、「delete を使用して解放されたメモリを使用するとクラッシュする必要がある」または「delete によって解放されたメモリをvalue X" - 解放されたメモリを使用してもクラッシュが発生しない、またはメモリを新しい値に変更できないとは言いません。

同様に、標準では、割り当てられていないものを new で解放した場合に何を期待すべきかについては述べていません。代わりに、それは「未定義の動作」であると言います。ほとんどの場合、 を使用しようとするとnew、ヒープが台無しになっているために失敗する可能性があります。

于 2013-06-10T11:11:18.017 に答える
0

オペレーターは、deleteメモリを管理する人に、削除されたポインタにアドレスが格納されている割り当てられたメモリがプログラムで不要になり、解放できることを通知することを目的としています。

C++ は、Win32 または Linux 用にコンパイルされているだけではないことに注意してください。メモリを異なる方法で管理するプラットフォームがさらに多くなる可能性があります。これが、標準が解放されたメモリに何が起こるかを明示的に定義しない理由です。特定のケースでは、メモリは空きとしてマークされていました (そのサイズの別の配列を割り当てて埋めた場合、以前に解放されたものは上書きされた可能性がありますが、必ずしもそうではありません)、その内容は破棄されませんでした。

このようなメモリ管理の実装は、パフォーマンスの目的に役立ちます。解放されたメモリがすぐに再び使用され、別のデータで埋められる場合、解放されたメモリをゼロ (または他の値) で上書きする意味は何ですか?

では、なぜそのメモリから読み取ろうとしても AV が発生しなかったのでしょうか? おそらく、その配列が存在するメモリのブロック全体がプロセス用に予約されていたため、独自のメモリから読み取ろうとしていた可能性があります。そのメモリに書き込もうとすると、AVが発生した可能性があります(そうではない場合もありますが、これも実装固有です)

一般的なルールは、削除によって解放されたメモリを使用しないことです。これは、標準が言うように、アクセス可能性についても、解放された後の内容についても保証されないためです。

于 2013-06-10T11:06:10.023 に答える