
よろしくお願いします。
クラスのメンバで3つのlongのポインタを宣言し、
コンストラクタ内でそれぞれにnewして領域を確保
しています。
質問1)newを失敗した場合には、そのポインタに
対してdeleteしてはいけないのでしょうか?
質問2)上記3つもエリアの確保のうち、2つめで失 敗した場合、1つ目のdeleteをしてやる
必要はあるのでしょうか?
catch(bad_alloc)でその処理をしようとおもうのですが、そもそもコンストラクタで例外を発生させるなと
かかれている書籍もあるようです。ただ、すでにそういう記載になってしまっており、できれば、いまの構造でメモリーリークを防げないかと思案しております。どなたか、よい方法をご存知の方いらっしゃいましたら、アドバイスいただけましたら幸いでございます。
No.4ベストアンサー
- 回答日時:
#2です。
> たとえば、bのnewでアロケーションを失敗した場合、
> Cのポインタは0で初期化された状態で、deleteしても
> 問題ないのでしょうか?
> また、Bのnewで失敗した状態のBにもdeleteを実行することになりますが、問題ないのでしょうか?
> deleteの順番がポイントなのでしょうか?
#3でも書かれていますが、0, NULLのdeleteは問題ありません。
deleteの順番はこの場合はどうでもいいです。
> また、この場合デストラクタA::~A()は実行されるのでしょうか?
されません。
例えば
A *objA = 0;
try {
objA = new A;
} catch (...) {
}
で例外が発生した場合、newの時点で例外発生->catchブロックへジャンプするので
objAに代入されず、objAは0のままです。
このため、objAのデストラクタを呼ぶことはできません。
したがってコンストラクタで例外が発生する場合は、
例外発生前にコンストラクタ内で確保したりソースを解放してからthrowしなければ
そのリソースを解放する手段がなくなります。
No.5
- 回答日時:
少し出遅れましたが、ひとつずつ回答していきます。
> 質問1)newを失敗した場合には、そのポインタに
> 対してdeleteしてはいけないのでしょうか?
原則としては駄目です。
というのも、newに失敗するとstd::bad_alloc例外が創出されるので、そのポインタには何も代入されず、不定状態になります。あらかじめ空ポインタで初期化しておくか、new(std::nothrow)を使って、失敗時に空ポインタが返るようにしておけば問題ありません。
> 質問2)上記3つもエリアの確保のうち、2つめで失敗した場合、1つ目のdeleteをしてやる
> 必要はあるのでしょうか
必要です。
根本的な問題を指摘するなら、コンストラクタの中で複数のnewを行うべきではありません。どうしてもの場合は、std::auto_ptrなど、スマートポインタを使うか、内部的にcatchして辻褄を合わせる(#2の方の方法)しかありません。
long型の配列を三つ用意するのであれば、std::vector<long>を三つ使う方が得策です。
# std::auto_ptrを使えないのは、new[]を使うからですよね?
No.3
- 回答日時:
#1です。
すいません間違ってました。ISOによるとNULLに対するdeleteは無視されるようです。
よってnewが失敗したポインタをdeleteしても問題ないようです。
No.2
- 回答日時:
自分ならこう書きます。
class A {
private:
A();
~A();
long *a,*b,*c;
};
A::A()
: a(0), b(0), c(0)
{
try {
a = new long;
b = new long;
c = new long;
} catch (...) {
delete c;
delete b;
delete a;
throw; //同じ例外をthrow
}
}
A::~A()
{
delete c;
delete b;
delete a;
}
コンストラクタで例外を投げないようにするには、
クラスAは初期化が完全に成功したかを示すフラグメンバ変数を持ち
コンストラクタで例外が起こらなかった場合そのメンバをtrueに設定する。
以降メンバ変数にアクセスする全ての関数の冒頭で
初期化が完全に終わっているかチェックする。
となり、変更箇所が多いためお勧めしません。
この回答への補足
この方法ですと現在のソースの修正がしやすいので、
もう少し教えていただきたいのですが、
たとえば、bのnewでアロケーションを失敗した場合、
Cのポインタは0で初期化された状態で、deleteしても
問題ないのでしょうか?
また、Bのnewで失敗した状態のBにもdeleteを実行することになりますが、問題ないのでしょうか?
deleteの順番がポイントなのでしょうか?
また、この場合デストラクタA::~A()は実行されるのでしょうか?
コンストラクタで例外を投げる方向で設計をしようと思います。よろしくお願いいたします。
No.1
- 回答日時:
>質問1)newを失敗した場合には、そのポインタに対してdeleteしてはいけないのでしょうか?
駄目です。newが失敗したポインタにはNULLが入っています。
>質問2)上記3つもエリアの確保のうち、2つめで失敗した場合、1つ目のdeleteをしてやる必要はあるのでしょうか?
1つ目のdeleteをしてやる必要があります。(解放しないと1つ目のメモリが確保されたままになります。)
std::auto_ptrを使ってはどうでしょうか?
http://www.doumo.jp/postgretips/tips.jsp?tips=78
ありがとうございました。
std::auto_ptrが使えればよかったのですが、
移植性を考えて作る必要があり今回は使用しない
方向で設計をせざるを得なくなりました。
勉強になりました。ありがとうございます。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Java JavaのSingletonパターンのprivateの持つ意味が分かりません。 5 2022/06/12 10:38
- 工学 下記のひろゆきの主張をどうみますか? 9 2023/02/20 14:10
- ヤフオク! Q1)ヤフオクで落札直後、裁判がどうこう言ういきなり出品者の身勝手で落札者に対して失礼な自己満ルール 6 2023/08/12 10:57
- C言語・C++・C# TCP/IP通信時のサーバーからの受信 2 2022/11/23 09:11
- Visual Basic(VBA) 列 A に同じ日が2つが必要です。 1 2023/03/28 07:25
- 事件・犯罪 刑法についてです 2 2022/06/04 03:11
- 事件・犯罪 刑法についてだれか助けてください。 2 2022/06/05 04:08
- 損害保険 自動車事故の過失割合についての簡易裁判 3 2023/07/30 23:53
- 楽器・演奏 ★ずっと疑問なのですが・・・? 5 2023/02/24 20:18
- 物理学 あのこれは、間違いと 3 2022/11/13 12:22
このQ&Aを見た人はこんなQ&Aも見ています
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
C言語特有の文法や概念について
-
ポインタのsizeofについて
-
ポインタ定義は必要なんですか?
-
マクロ,クラス
-
ファイルポインタのヘッダーフ...
-
C言語のvoid型ポインタ変数につ...
-
連結リスト 要素の入れ替え
-
配列3個へのポインタを返す関数
-
[C言語] NULLは必ず0(番地)です...
-
ポインタのミスでOS壊れるの...
-
structをポインタ宣言時の領域
-
C言語の練習
-
sprintf 初歩的な質問
-
gccでMAKEINTRESOURCEするとdif...
-
init関数の意味
-
関数のパラメタ(C++)
-
戻り値で構造体を返すことは可...
-
引数のポインタ変数をローカル...
-
プログラミング C++
-
#include <stdio.h> #include <...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
セグメントエラー
-
C言語のポインタに直接アドレス...
-
init関数の意味
-
Run-Time Check Failure #3とい...
-
戻り値で構造体を返すことは可...
-
ExcelVBAでのkernel32(64bit)
-
アプリを32bitから64bit移行
-
参照型で受け取った引数をポイ...
-
fopne で失敗する原因
-
PASCALとFARの意味
-
LPSTR型の初期化について
-
CWnd::EnableWindow()の扱い方
-
ポインタについて
-
プーさんのマウスポインタを教...
-
連結リスト 要素の入れ替え
-
ハンドルはポインタか
-
C++で関数ポインタから関数名を...
-
自作DLLの引数について、ポイン...
-
NULLポインタが0でない処理系と...
-
TCHAR文字列内の検索について
おすすめ情報