• ベストアンサー

デストラクタについて

 C++初心者です。 delete [] tt ; でデストラクタが要素数だけ実行されるのは 確認しています。 ところがその実行後に、例えば、 cout << tt[3].test() << endl ; としますと、ちゃんと表示されます。 消滅したはずのオブジェクトが使えるのはど うしてでしょうか? どなたかお教え願えませんでしょうか。 どうぞよろしくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
  • neuron-x
  • ベストアンサー率52% (139/266)
回答No.2

CTest* ptr = new CTest[100]; この時点で、メモリ上に CTestのポインタ(ptr)用の領域と、 CTest[100]分の領域が確保されます。 ptrは、CTest[100]の先頭アドレスを指しています。 delete[] ptr; これで、CTest[100]分の領域が開放されます。 ここでの解放とは、「この領域は使わないからこのエリアを書き換えてもいいよ」とするだけで、実際はその領域には以前の内容が書き込まれたままです。 この状態で、ptr->method(); としても、その領域が他の何かで上書きされていなければ正常に動作します。(詳しくいうと、動作しているように見えます) しかし、解放済みの領域の内容は不定(何が入っているか分からない)です。ですから、偶然前の状態が残っていて動作する場合もありますし、他の内容で上書きされていればプログラムの動作は予測不可能となります。

jasmine002
質問者

お礼

 分かりやすいご教示ありがとうございました。 NO1さんにも書きましたが、コンパイルがすんなりと 成功するのに対して疑問が残りますが、それは私など にはまだまだ分からない事情があってそのような仕様 になっているのでしょうね。現象面での状況がよく分 かりました。どうもありがとうございました。

その他の回答 (1)

  • nitscape
  • ベストアンサー率30% (275/909)
回答No.1

>消滅したはずのオブジェクトが使えるのはど うしてでしょうか? メモリ上にはまだ残っているからだと思います。どこかでメモリを使うと(一部もしくは全部)上書きされりして使えなくなるかと思います。 int main() { char* psz; strcpy(psz,"abcdefg"); printf("%s",psz); return 0; } 上のようなプログラムはpszに対してメモリを確保していないので動かないように思いますが。。。プラットフォームにもよりますが見た目だけは正常に動きます。 この例も質問文の例も言ってみれば"不正な処理"なので試して使えるからといって使い続けるのはやめた方がいいと思います。

jasmine002
質問者

お礼

早速のご教示ありがとうございます。 makeまですんなりいった以上、その とおりの動作をするということです ね。どうしてコンパイルが成功する のか、そのような仕様になっている からでしょうが、疑問がないわけで はありませんが、現象面での事態が よく分かりました。どうもありがと うございました。

関連するQ&A

  • コンストラクタ・デストラクタ

    プログラミング言語はC++ C++を触り始めたばかりの素人です。 コンストラクタとデストラクタについて質問です。 下記に参考にしているウェブページから簡潔にしてコードを書いてみました。 コンストラクタ、デストラクタの中はそれぞれに、○○が呼び出されましたと書いてあるだけでよく分からなかったので別のウェブページを見たら コンストラクタは Sample::Sample(){ n=0; } みたいな例があったのですが、このように変数に予め何かの値を代入しておくという事で合ってますか? デストラクタは理解できていません。 下記の例では、どのような処理を書けばいいのでしょうか? #include<iostream> using namespace std; class Sample { private: int n; public: void Show(); Sample(); ~Sample(); }; void Sample::Show() { cout << n << endl; } Sample::Sample() { // n=0; std::cout << "コンストラクタが呼び出されました" << std::endl; } Sample::~Sample() { // どんな処理? std::cout << "デストラクタが呼び出されました" << endl; } main() { Sample sample; sample.Show(); return 0; } 実行結果 コンストラクタが呼び出されました 1     ←コンストラクタ関数内の//を削除で0になることは確認 デストラクタが呼び出されました

  • C++のクラスについて

    /*以下のコメントがある行では何故、コンストラクタ(class2::class2)を指定出来ないのですか? デストラクタ(class2::~class2)の場合も問題なくコンパイルが通り、実行できます (http://codepad.org/1oJkxjyZ の23行目) 開発環境 Windows XP SP3 コンパイラ:GCC 実行結果 class1のコンストラクタ class2のコンストラクタ aiueoの実行 class2のデストラクタ class1のデストラクタ */ #include<iostream> class class1; class class2; class class1{ public: class1(); ~class1(); private: class2*pointer; }; class class2{ public: class2(); ~class2(); void aiueo(); }; class1::class1(){ std::cout<<"class1のコンストラクタ"<<std::endl; pointer=new class2(); pointer->aiueo(); //aiueoを~class2に置き換えてもコンパイル出来るが、class2だとエラーが出る } class1::~class1(){ delete pointer; std::cout<<"class1のデストラクタ"<<std::endl; } class2::class2(){ std::cout<<"class2のコンストラクタ"<<std::endl; } class2::~class2(){ std::cout<<"class2のデストラクタ"<<std::endl; } void class2::aiueo(){ std::cout<<"aiueoの実行"<<std::endl; } int main(){ class1 test1; return 0; }

  • C++の話です。

    C++の話です。 静的メンバ変数としてクラスを宣言した場合、デストラクタが呼ばれていないようなのですが、呼ぶ方法はありませんか? できれば「new」「delete」を使わずできると理想的です。 分かる方教えていただけると助かります。 以下、サンプルコードです。 「デストラクタが呼ばれました」と出力されない上、デバッガを使って試してみましたが、やはり呼ばれていないようです。 #include<iostream> class Test{   public:     ~Test(){       std::cout<<"デストラクタが呼ばれました"<<std::endl;     } }; class A{   private:     static Test T; }; int main(){   A a;   return 0; }

  • 添字範囲エラー送出とデストラクタについて

    添字範囲エラー送出とデストラクタについて 下記のように(1)SiZE=5,(2)num=6 を投入した場合、添字演算子[]関数で(3)添字範囲エラー送出(size=5,I=5)の時、 IdxRngErr例外を発生し、(4)デストラクタを呼んでcatch((5)catch (IntArray::IdxRngErr&)で捕捉される。 質問 IdxRngErr例外を発生により、デストラクタを呼ばれる理由を教えて頂きたい。 *********************************************************************************** main() { int size, num; cout << "要素数:"; cin >> size;   (1) 5を投入 cout << "データ数:"; cin >> num; 、 (2) 6を投入 f(size, num); return 0; }/ *************************************************************************************** //===== 整数配列クラス ======// class IntArray { int size; // 配列の要素数 int* vec; // 先頭要素へのポインタ ~IntArray() { delete[] vec; } // (4)デストラクタよりIdxRngErrがcatch(5)される。 int& operator[](int i) { // 添字演算子[] if (i < 0 || i >= size) throw IdxRngErr(this, i); (3)// 添字範囲エラー送出(size=5,I=5)の時, return vec[i]; } ******************************************************************************************* / //--- 要素数sizeの配列にnum個のデータを代入して表示 --// void f(int size, int num) { try { IntArray x(size); for (int i = 0; i < num; i++) { x[i] = i; cout << "x[" << i << "] = " << x[i] << '\n'; } }    (5)catch (IntArray::IdxRngErr& x) { cout << "添字オーバフロー:" << x.Index() << '\n'; return; i

  • [PHP] デストラクタについて教えて下さい

    あるPHPの入門書にデストラクタについての解説があります。 *デストラクタ 「コンストラクタとは反対に、オブジェクトが破棄されるタイミングで実行されるのがデストラクタです。名前は __destructに固定されている。 デストラクタには、クラスの中で使用したリソースを破棄するなど、主に終了するときの処理を記述するのが一般的です。」 とあります。 以下のような記述をしました。(person.php) <?php class Person{ public $lastName; public $firstName;  public function __construct($lastName, $firstName){ $this->firstName = $firstName; $this->lastName = $lastName; } public function show(){ print "<p>私の名前は {$this->lastName} {$this->firstName}です。</p>"; } public function __destruct(){ print "<p>インスタンスが破棄されました。<p>";  } } ?> 上の記述をインスタンス化する記述です。(instancne.php) <?php require_once('person.php'); $p = new Person('田中', '幸太郎'); $p->show(); ?> <表示結果> 私の名前は 田中 幸太郎です。 インスタンスが破棄されました。 となります。試しにもうひとつインスタンスを追加します。 <?php require_once('person.php'); $p = new Person('田中', '幸太郎'); $p->show(); $p1 = new Person('鈴木', '京子'); $p1->show(); ?> <表示結果> 私の名前は 田中 幸太郎です。 私の名前は 鈴木 京子です。 インスタンスが破棄されました。 インスタンスが破棄されました。 説明にある、 「オブジェクトが破棄されるタイミングで実行されるのがデストラクタです。」 「デストラクタには、クラスの中で使用したリソースを破棄するなど、主に終了するときの処理を記述するのが一般的です。」 これらの意味がわかりません。 コンストラクタの 「new 演算子によってインスタンス化されるタイミングで実行される」 「プロパティの初期化」 などの意味は理解できているつもりです。 デストラクタを使うと「オブジェクトが破棄される」、「クラスの中で使用したリソースを破棄する」と ありますが、『一度インスタンスを作るとクラス内のリソースが破棄されるのかな?』と思い ためしにもう一つインスタンスを作成しました。上記の通り問題なく使えています。 膨大な記述になると、クラス、この場合は 「class Person」」は再利用出来なくすると言った意味になるのでしょうか? 他の教材やネットで検索してみたりしたのですが、イメージがつかめません。 以下のPHP公式のサイトから考えてみると、クラス内で参照できるものがなければ、コールされるという風に解釈できるかもしれませんが、意味がわかりません。 デストラクタ(__destruct)はコンストラクタ(__construct)の反対というように記述されているものもありますが余計に意味が分かりません。 初学者にもわかるようにデストラクタについて教えてもらえないでしょうか? またどういうケースで利用するのかもよく分かりません。 そのあたりも併せて教えて下さい。 宜しくお願いいたいます。 (参考) デストラクタ __destruct(): void PHP には、C++ のような他のオブジェクト指向言語に似たデストラクタの概念があります。 デストラクタメソッドは、 特定のオブジェクトを参照するリファレンスがひとつもなくなったときにコールされます。 あるいは、スクリプトの終了時にも順不同でコールされます。 https://www.php.net/manual/ja/language.oop5.decon.php

    • ベストアンサー
    • PHP
  • shared_ptrからpimplのデストラクタ呼び出し

    pimplイディオムの勉強をするために以下のようなプログラムを作りました。 //MySharedPtr.h template<typename tnT> class MySharedPtr {  tnT *mPtr; public:  MySharedPtr(tnT *ptr) : mPtr(ptr) {}  ~MySharedPtr() { delete mPtr; } //(1) }; //Foo.h class Foo {  struct stImpl;  MySharedPtr<stImpl> mImpl; //(2) public:  Foo(); }; //Foo.cpp Foo::stImpl {  ~stImpl() { cout << "xxx" << endl; } //(3) }; Foo::Foo() : mImpl(new stImpl) {} //main.cpp int main() {  Foo foo; } これをコンパイルすると、(1)の所でtnTのデストラクタが見つからない旨のワーニングが出て、mainを実行するとstImplのデストラクタが呼ばれずに(3)の出力は出ません。ただ、(2)をboost::shard_ptrに変えるとワーニングも出ないし(3)の出力もされます。(2)の箇所でstImplが宣言だけなのは両者とも同じだと思うのですが、なぜboostはワーニングが出ないのでしょうか。また、MySharedPtrでもワーニングを出さないようにすることはできるのでしょうか。もちろん、スマートポインタを実装するよりもboostを使用した方が良いとは思うのですが、何でboostはうまくいくのか不思議に思い、質問させていただきました。

  • アドレスの計算が合わない

    C++でポインタの勉強をしています。 その中でアドレスについての以下のような記述がありました。 <例1> struct { int a; int b; int c; } oshiete; cout << &oshiete.a << endl; cout << &oshiete.b << endl; cout << &oshiete.c << endl; このように、構造体の中で宣言された変数の領域は連続した場所を確保するというものでした。これの実行結果は以下の様になりました。 0013FF5C 0013FF60 0013FF64 int型のバイト数は4でしたので、それぞれの変数の先頭アドレスは4つ間隔になっています。しかし、これの2つ目の変数bをshort型に変えても同じ結果が返ってくるのです。short型のバイト数は2です。 <例2> struct { int a; short b; int c; } oshiete; cout << &oshiete.a << endl; cout << &oshiete.b << endl; cout << &oshiete.c << endl; 結果: 0013FF5C 0013FF60 0013FF64 そして変数aもshort型にすると、やっと納得のいく結果になりました。 <例3> struct { short a; short b; int c; } oshiete; cout << &oshiete.a << endl; cout << &oshiete.b << endl; cout << &oshiete.c << endl; 結果: 0013FF60 0013FF62 0013FF64 なぜ<例2>ではint, short, intの順で宣言したのにアドレスが全て4つ間隔なのでしょうか?例えば先頭アドレスが0013FF5Cであるなら、 0013FF5C 0013FF60 0013FF62 のように1つ目と2つ目のアドレス差は4、2つ目と3つ目のアドレス差は2になるはずだと思うのですが。

  • char型変数のアドレスを coutで表示するには

    #include <iostream> using namespace std; int main() { bool b; int i; short s; long l; float f; double d; char c; //上で宣言した変数のアドレスを表示 cout << "bool &b " << &b << endl; cout << "int &i " << &i << endl; cout << "short &s " << &s << endl; cout << "long &l " << &l << endl; cout << "float &f " << &f << endl; cout << "double &d " << &d << endl; cout << "char &c " << &c << endl; //「char &c 」とのみ表示される cout << '\n'; //char型のみ printf で再表示 printf("char &c %p\n", &c); //「char &c ********」と表示される return 0; } 上のプログラムを実行すると cout << "char &c " << &c << endl; のところだけ、アドレスが表示されません。 printfを使えば、char型の変数のアドレスも表示されるのですが…。 coutを使ってchar型のアドレスを表示させるにはどうすればいいのでしょうか。 よろしくお願いします。

  • (C++)スマートポインタをメンバ変数で使いたい

    Viual Studio 2013を使ってC++のコードを書いています。 以下のコードで、new-deleteの クラス生成をスマートポインタで置き換えたいのですが、 うまくいきません。具体的には/* not smart */の部分を スマートポインタで置き換えたいが、C2059のエラーが出てきて コンパイルできないのが理解できていません。 どなたかわかる方教えていただければ幸いです。 よろしくお願いします。 // ----コードは以下---- #include <memory> #include <iostream> class Hoge { public: Hoge(){ std::cout << "constructed!" << std::endl; }; ~Hoge(){ std::cout << "destructed!" << std::endl; }; private: }; class Hogehoge { public: Hogehoge(){}; ~Hogehoge(){ delete test; /* not smart */}; private: // error C2059 w/ VS2013 // std::unique_ptr<Hoge> test(new Hoge); Hoge* test = new Hoge; /* not smart */ }; void main() { Hogehoge foo; }

  • cgiで表示したフレームに結果を表示したい

    cgiで作成した画面でフレームを左右に分割したのですが、 内容が表示できません。 cgiで作成したフレーム分割した画面に 結果を表示させる方法を教えてください。 (cgiの記述の仕方が間違えているのか?  htmlの<frameset>、<frame>タグの設定の仕方が悪いのか?  そもそも全体の流れの考え方が間違えているのか?  分からず、行き詰ってしまっています…。) どうか宜しくお願いいたします。 ■作成したファイルは下記のような仕様です。 TEST.html :ボタン操作で、AAA.ccを実行する。 AAA.cc   :作成した画面上のリンクをクリックすることでBBB.ccを実行する。         画面は左右にフレーム分割し、         左側フレームにAAA自身の実行結果として取得したファイルのリストを         右側フレームにファイルリストでリンクした画面を表示させる。 BBB.cc  :AAAから指定されたリンクを加工して開く。 ■ファイルの内容は下記のような感じです…。 >>>TEST.html <form action="**パス**/AAA"> <input type="hidden" name="path" value="**AAAに渡すデータ**"> <input type="submit" value="リスト"> </form> >>>AAA.cc cout << "<frameset cols=\"30%,*\">" << endl; cout << "<frame src=\"**パス**/\" name=\"listA\">" << endl;  :(省略) cout << "<a href=\"**パス**/BBB?path=" << BBBに渡すデータ << "\" target=\"ContensB\" >" << endl;  :(省略) cout << "<frame src=\"**パス**/\" name=\"ContentsB\">" << endl; cout << "<html>" << endl; cout << "<head>" << endl; cout << "<title>Contents</title>" << endl; cout << "</head>" << endl; cout << "<body>" << endl; cout << "</body>" << endl; cout << "</html>" << endl; cout << "</frameset\">" >>>BBB.cc  :(省略) cout << getContents() << "<br>" << endl;  :(省略) どうか宜しくお願いいたします。

    • ベストアンサー
    • CGI

専門家に質問してみよう