質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

1回答

2135閲覧

デストラクタとdelete

BeatStar

総合スコア4958

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2018/04/28 02:59

趣味でC++やっています。

デストラクタというより、deleteに関して質問があります。

例えば、

C++

1// インターフェースクラス 2class IClass{ 3 public: 4 ~IClass(){} 5 virtual setOption1( bool b ) = 0; 6 virtual option1( void ) const = 0; 7 // 他にもvirtualなメンバ関数あり 8}; 9 10class ClassA : public IClass{ 11 public: 12 ClassA( int id ) : id_(id){} 13 ~ClassA(){} 14 void setOption1( bool b ){ this->op1_ = b; } 15 bool option1( void ) const{ return this->op1_; } 16 void setOption2( bool b ){ this->op2_ = b; } 17 bool option2( void ) const{ return this->op2_; } 18 // 他にもメンバ関数があるとして 19 private: 20 int id_; 21 bool op1_; 22 bool op2_; 23 // 他にもメンバ変数があるとして 24}; 25 26// 同様にClassBもあるとする 27 28// 実際に動かすクラス 29class Doer{ 30 public: 31 Doer( IClass* obj ) : obj_(obj){} 32 ~Doer(){ 33 delete obj_; // <- ここが問題部分(1) 34 } 35 bool isEnabled( void ) const{ /* 使用可能かどうか */ } 36 /* 37 IClassを継承したClassA,Bのいずれかのオブジェクトがobj_に格納されているので、 38 それを用いて処理をするメンバ関数がいくつかあるとする 39 */ 40 private: 41 IClass* obj_; 42};

これをWindows APIで構造体を引数とする関数を使う感じで

C++

1ClassA* item = new ClassA(1); 2item->setOption1( true ); // 情報の設定 3item->setOption2( true ); // 同上 4 5Doer* doer = new Doer( item ); // 先ほどインスタンス化したもので生成 6if( doer->isEnalbed() )... 7 8delete doer; 9 10delete item; // <- ここが問題部分(2)

のように、最初に扱われるクラスオブジェクトの設定をして渡す場合はどうなるのでしょうか?

イメージとしてはJavaでの

Class2 obj = new Class2( new Class1(1,10,20) );

のようにnewしてすぐ渡すことに対応してみようかなと思ったため、上記のコードを書いてみました。

ここで問題に思っているのは、

「deleteをすべき場所はどこか」です。

main関数等のような呼び出し側でdeleteすればいいかもしれませんが、

Javaみたいな書き方はできないかな?と思ったので、それ以外の方法として

「デストラクタでもdeleteし、呼び出し側でもdeleteする」です。

ですが、これってOKなのでしょうか?

どこかのサイト ( 多分、「C++の迷信」みたいなサイトだった気がします... ) には

「deleteにNULL ( nullptr ) を渡しても処理せずにreturnするような状態だから...」とありました。

( 話題としては「コンストラクタから例外を投げるのはアリ?ナシ?」系でしたが。 )

内部のことなので確かめようがありません...

[ 情報 ]
言語: C++

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

こんにちは。

呼び出し側(new Doerする側)で、「newしたClassAへのポインタ」を保持しない場合、呼び出し側でdeleteするのは面倒ですし構造が汚くなりがちです。
Doerのデストラクタでデストラクトするのが比較的良く使われる手法と思います。

ただし、その際はDoerのインスタンスを単純にコピーするようなコードを書くと、多重deleteしてしまいます。

C+++

1Doer* doer = new Doer( new ClassA() ); 2{ 3 Deor copy_to = *doer; 4 // 何らかの処理 5 6} // obj_は単純にコピーされているため、ここでdelete obj_;される。 7 // これは最初にnew ClassA()で確保したインスタンス 8 9delete doer; // ここでも再度 delete obj_;をやってしまい、多重解放となる。

そのようなバグを回避するためにコピーコンストラクタとコピー演算子をdeleteしておくと、間違ってコピーするコードを書いた時にコンパイルエラーになるので安全性が高まります。

投稿2018/04/28 03:17

編集2018/04/28 03:31
Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

BeatStar

2018/04/28 03:34

ご回答ありがとうございます! コピーコンストラクタ と コピー演算子をdelete ( 使えなくする ) ですか...なるほど。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問