デストラクタとdelete
解決済
回答 1
投稿
- 評価
- クリップ 0
- VIEW 1,000
趣味でC++やっています。
デストラクタというより、deleteに関して質問があります。
例えば、
// インターフェースクラス
class IClass{
public:
~IClass(){}
virtual setOption1( bool b ) = 0;
virtual option1( void ) const = 0;
// 他にもvirtualなメンバ関数あり
};
class ClassA : public IClass{
public:
ClassA( int id ) : id_(id){}
~ClassA(){}
void setOption1( bool b ){ this->op1_ = b; }
bool option1( void ) const{ return this->op1_; }
void setOption2( bool b ){ this->op2_ = b; }
bool option2( void ) const{ return this->op2_; }
// 他にもメンバ関数があるとして
private:
int id_;
bool op1_;
bool op2_;
// 他にもメンバ変数があるとして
};
// 同様にClassBもあるとする
// 実際に動かすクラス
class Doer{
public:
Doer( IClass* obj ) : obj_(obj){}
~Doer(){
delete obj_; // <- ここが問題部分(1)
}
bool isEnabled( void ) const{ /* 使用可能かどうか */ }
/*
IClassを継承したClassA,Bのいずれかのオブジェクトがobj_に格納されているので、
それを用いて処理をするメンバ関数がいくつかあるとする
*/
private:
IClass* obj_;
};
これをWindows APIで構造体を引数とする関数を使う感じで
ClassA* item = new ClassA(1);
item->setOption1( true ); // 情報の設定
item->setOption2( true ); // 同上
Doer* doer = new Doer( item ); // 先ほどインスタンス化したもので生成
if( doer->isEnalbed() )...
delete doer;
delete 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++
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
checkベストアンサー
0
こんにちは。
呼び出し側(new Doerする側)で、「newしたClassAへのポインタ」を保持しない場合、呼び出し側でdeleteするのは面倒ですし構造が汚くなりがちです。
Doerのデストラクタでデストラクトするのが比較的良く使われる手法と思います。
ただし、その際はDoerのインスタンスを単純にコピーするようなコードを書くと、多重deleteしてしまいます。
Doer* doer = new Doer( new ClassA() );
{
Deor copy_to = *doer;
// 何らかの処理
} // obj_は単純にコピーされているため、ここでdelete obj_;される。
// これは最初にnew ClassA()で確保したインスタンス
delete doer; // ここでも再度 delete obj_;をやってしまい、多重解放となる。
そのようなバグを回避するためにコピーコンストラクタとコピー演算子をdeleteしておくと、間違ってコピーするコードを書いた時にコンパイルエラーになるので安全性が高まります。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.23%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
2018/04/28 12:34
コピーコンストラクタ と コピー演算子をdelete ( 使えなくする ) ですか...なるほど。