アプリ版:「スタンプのみでお礼する」機能のリリースについて

こんにちは。

C++では、プログラムの終了時に、全てのクラスオブジェクトは、デストラクタが呼び出されて破棄されますが、プログラムの途中で、クラスオブジェクトを明示的に破棄する方法はあるのでしょうか?

例えば、new演算子によってメモリを動的に割り当てたポインタなら、delete演算子で破棄できますが、
クラスオブジェクトにdelete演算子は使えないようです。

何かいい方法を知っておられる方がいらっしゃれば、是非アドバイスを頂きたいと思います。

A 回答 (8件)

ClassA *p = new(buf) ClassA;



ClassA *p = new ClassA;
の意味は違います. 後者はメモリを割り当てますが, 前者ではメモリの割り当ては行われません. placement new なんかで調べてもらうといいかな.
    • good
    • 1
この回答へのお礼

御回答ありがとうございます。

placement newは、new演算子関数に、引数を与える機能のようですね。
はじめて知りました。
今回の場合、bufの指すアドレスを、pが指すようにしているのだと分かりました。
(printf("%p", buf); と pring("%p", p); で表示されるアドレス値が同じでした。)

お礼日時:2011/09/17 06:46

ちょっと気になるんですが明示的に破棄したいコードがあるんですか?


それとも単なる興味?
いや興味ならいいんですが、ただ素直にnew-deleteすればいいのになぁと思ったので。

>No1の型の回答に書いた通り、「クラスオブジェクト」とは、何らかのクラス型のオブジェクトの事です。
>普通はどのように呼ぶべきなのでしょうか?
自動変数のクラス?
私なら簡単なソースを書いて「このローカル変数nを明示的に破棄したい」という風な書き方にしますかね。

>普通は単に「オブジェクト」というのかもしれませんが、普通の変数など、他のオブジェクトとの区別をするために、その様に読んでいます。
str_type *p = new str_type; //←newしたデータ=オブジェクト(=インスタンス)
何か勘違いしてるみたいですけど、オブジェクトって物凄く広い意味で使われるので曖昧回避したい場合は極力使わない方がよい単語です。
ちなみにNo.1氏の「class_a」や上に書いた「*p」なんかをインスタンスと呼びます。
インスタンスもオブジェクトの一種です。(厳密に言うと違うものらしいですが)
    • good
    • 1
この回答へのお礼

御回答ありがとうございます。

>ちょっと気になるんですが明示的に破棄したいコードがあるんですか?
いや、そういうわけではありません。

>何か勘違いしてるみたいですけど、オブジェクトって物凄く広い意味で使われるので曖昧回避したい場合は極力使わない方がよい単語です。
ちなみにNo.1氏の「class_a」や上に書いた「*p」なんかをインスタンスと呼びます。

御指摘ありがとうございます。
http://itpro.nikkeibp.co.jp/free/NIP/NIPCOLUMN/2 …
にオブジェクトとインスタンスについて、分かりやすく説明されていました。
間違いに気がついて良かったです。

お礼日時:2011/09/17 06:35

すでに #5 の方が回答されていますが、デストラクタはオブジェクトを破棄するためにあるのではなく、オブジェクトが破棄されるときに後処理をするためにあります。

デストラクタ自体は、他のメンバ関数(メソッド)と同様に1メンバ関数に過ぎませんが、C++ の仕組みとして、オブジェクトが破棄されるときにデストラクタがあれば自動的にコールするようになっている、という仕組みになっています。デストラクタをプログラム中から意図的にコールするというのは、あまりやらないですね・・・・・・・。

いろいろ試してまた疑問が出てきて解決していけば、そうやっていくうちにいろんな間違って覚えていたことが修正されていくのは技術向上の鉄則です。頑張ってください^^。
    • good
    • 0
この回答へのお礼

御丁寧にありがとうございます。
頑張ります。

お礼日時:2011/09/16 16:04

> プログラムの終了時に、全てのクラスオブジェクトは、


> デストラクタが呼び出されて破棄されますが
逆ですね。
「オブジェクトが破棄される時にデストラクタが呼び出される。」
だと思います。

なので、追加質問でも
> ob.str_type::~str_type();
では、単にデストラクタを明示的に呼び出しただけでobは破棄されず
スコープから外れた時に破棄されてもう一度デストラクタが呼ばれた
のだと思います。
    • good
    • 0
この回答へのお礼

御回答ありがとうございます。

なるほど、僕が勘違いしていたみたいですね。
という事は、デストラクタを呼び出しただけでは、
オブジェクトは破棄されないのですね。
よーく分かりました。

お礼日時:2011/09/16 10:32

多分、そんなことはないと思いますが…


もしかして、クラスオブジェクトって、クラスメンバー(クラスの静的メンバー, クラスのstatic変数)のことを指しているわけではないんですよね?
    • good
    • 0
この回答へのお礼

御回答ありがとうございます。
分かりにくくて申し訳ございません。
No1の型の回答に書いた通り、「クラスオブジェクト」とは、何らかのクラス型のオブジェクトの事です。
普通はどのように呼ぶべきなのでしょうか?

お礼日時:2011/09/16 00:03

無理すれば



char buf[sizeof (ClassA)];
ClassA *p = new(buf) ClassA;
// なんかする
p->ClassA::~ClassA();

ともできるけど普通はスコープで対応する... あぁそうか, 「プログラムの終了時に、全てのクラスオブジェクトは、デストラクタが呼び出されて破棄されますが」という認識がおかしいんだ.

この回答への補足

Tacosanさん、
ClassA *p = new(buf) ClassA;
は、pにサイズbufのメモリを動的に割り当て、
ClassA型オブジェクトの先頭を指すようにするという意味でよろしいのでしょうか?
だとすると、単に
ClassA *p = new ClassA;
だけでも良いと思うのですが、如何でしょうか?

あと、
ClassA *p = new(buf) ClassA;
で、オブジェクトポインタにメモリを割り当てた後、
そのまま終了しても、ClassAクラスのデストラクタは呼び出されませんでした。
オブジェクト変数を生成しない限り、デストラクタは呼び出されないのでしょうか?



オブジェクトポインタ

補足日時:2011/09/16 03:36
    • good
    • 0
この回答へのお礼

Tacosanさん、いつも御回答、ありがとうございます。

p->ClassA::~ClassA();
のように、デストラクタを明示的に呼び出せる事は知りませんでした。

あまり大きなプログラムを作成した事がないので、
「普通はスコープで対応する」という事は、考えた事がありませんでした。
これからは、そういった認識を持つようにします。

お礼日時:2011/09/16 00:08

#1 の方の回答で、やりたいことができるのでは、と思うのですが、オブジェクトのライフタイムの認識があってないかもしれません・・・・・・。



オブジェクトのライフタイムは記憶クラスの「スコープ内」です。スコープが終了するときには破棄されます。関数やメソッド、{}で囲まれたブロック内で宣言しているオブジェクト変数(auto 記憶クラス)であればそれらが終了する時です。もちろん static などで確保されているクラス変数は、プログラムが終わるまで破棄されません。

この回答への補足

追加質問です。
str_typeというクラスを定義し、main関数で
str_type ob;
ob.str_type::~str_type();
のようにすると、コンストラクタとデストラクタが呼び出されたのですが、
プログラムの終了時に、デストラクタがもう一度呼び出されました。
ob.str_type::~str_type();
によって、obは破棄されたはずなのに、なぜこういった事が起こるのでしょうか?

補足日時:2011/09/16 03:42
    • good
    • 0
この回答へのお礼

御回答ありがとうございます。

今まで、オブジェクトのライフタイムについては、深く考えた事がありませんでした。
特に、「記憶クラスのスコープ」というものの認識があいまいなようです。
勉強し直してきます。

お礼日時:2011/09/16 00:13

……クラスオブジェクト?なんのこっちゃ?



とりあえずやりたいことはこれかな?

class ClassA
{
};

int main(int argc, char** argv)
{
 ClassA class_a;
 // 何らかの処理-1
 delete class_a; // もちろん間違いだけどこれと似たようなことがやりたい
 // 何らかの処理-2
 return 0;
}

もし上のようなことがしたいならば、変数のスコープを利用して以下のようにすれば可能です。

int main(int argc, char** argv)
{
 {
  ClassA class_a;
  // 何らかの処理-1
  // オブジェクト破棄のための文は書く必要がない
 }

 // 何らかの処理-2
 return 0;
}

この回答への補足

試させていただきた所、 } のところできちんと破棄されました。
ありがとうございました。

補足日時:2011/09/16 00:02
    • good
    • 0
この回答へのお礼

御回答ありがとうございます。

僕が言っている「クラスオブジェクト」は、記述して下さったプログラムのclass_aの事です。
普通は単に「オブジェクト」というのかもしれませんが、普通の変数など、他のオブジェクトとの区別をするために、その様に読んでいます。
僕がやりたかった事は、当に最初に記述していたプログラムのような事です。
2つ目のプログラムでは、main関数の中で、{ }で括った部分のオブジェクトは、処理が } まで進むと自動的に破棄されるというものですよね。
そのような事ができるとは知りませんでした。
試させていただきます。

お礼日時:2011/09/15 23:59

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!