2017-08-29 2 views
0

配列や行列のような動的メモリ割り当てを使用するクラスAがあるとします。オブジェクトAの作成中に、コンストラクタを介して、どのくらいのメモリ空間が割り当てられているかを決定するパラメータが渡されます。意図した方法では作成できないオブジェクトの処理C++

class A 
{ 
    int * ptr; 
    int size; 
    void allocate() noexcept; 
    void destroy() noexcept; 
    public: 
    A(int) noexcept; 
    ~A() noexept; 
} 
void A::destroy() noexcept 
{ 
    if(ptr!=nullptr) 
    delete [] ptr; 
} 
A::~A() noexcept 
{ destroy();} 
void A::allocate() try 
{ 
    ptr = new int[n]; 
} 
catch (std::bad_alloc & ex) 
{ 
    std::cerr << ex.what(); 
    destroy(); 
} 
A::A(int n) noexcept : size(n) { allocate(); }; 

これらの種類のものは、設計上賢明ですか?意図した方法で作成できないオブジェクトはどうなりますか?それはゾンビのように「生きている」ままであろうか、それとも破壊されるだろうか?

マトリックスが複数の新しいステートメントで割り当てられるマトリックスシナリオで何をすべきか?

スマートポインタ、STLとその種のものはここではオプションではありません。

READ ME:このクラスは純粋にこの種の問題のために作られたデモンストレーションクラスです。それは0/3/5の規則に従わない。なぜなら、質問のために書くのはあまりにも多くのコードであり、この質問にとっては重要ではないからである。すでにこれらの問題に関する質問がたくさんあります。

+1

なぜ投げるべきものを投げ捨てるのはなぜですか? – juanchopanza

+1

なぜ失敗した割り当てで 'destroy'を呼び出すのですか?割り当てに失敗した場合は、「削除」する必要がないことを意味します。 –

+1

"これは良い解決策ですか?" - どんな問題? –

答えて

1

Q.これらの種類のものは良い習慣であり、賢明な設計ですか?

A.これを実行することに害はなく、要件によって異なります。一般に、これはコンストラクタが決してスローしないようにしたい場合(これはおそらくあなたの意図です)、割り当てられているデータがオブジェクトの操作に重要でない場合は意味があります。ほとんどの場合、コンストラクタにエラーがある場合に例外をスローするのが常にベストです。これを使うと、ptr []にアクセスするたびにNULLをチェックする必要があることに注意してください。

Q.意図した方法で作成できないオブジェクトはどうなりますか? ゾンビオブジェクトのように「生きている」ままであろうか、それとも破壊されるだろうか?

A.これは2通りの方法で発生します。 1.オブジェクトA自体のメモリ割り当てに失敗しました。この場合、メモリの割り当てに使用される方法に依存します。その "新規"の場合、デフォルトで例外がスローされます。 2. allocateの整数配列にメモリを割り当てられません。この場合、例外が発生します。 catchブロックでは、tryブロックが失敗する唯一の方法として、n個の整数の配列に対してメモリを割り当てることができないため、destroy()を使用してptrの割り当てを解除する必要はありません。 Aのコンストラクタはこの失敗を隠し、オブジェクトAに割り当てられたメモリはそのままの状態になります。

Q.マトリックスが複数の新しいステートメントで割り当てられているマトリックスシナリオで何をすればよいですか?

A. forループ/複数の新しい文でptrのメモリを割り当てるとどうなるでしょうか?その場合、動作は同じですが、ptr []にすでに割り当てられているメモリはそのままの状態になり、ptr []に割り当てられたメモリの割り当てを解除するにはcatchブロックでdestroy()を呼び出す必要があります。破壊時には、再度、各配列要素のNULLを個別にチェックし、割り当てを解除する必要があります。

0

いいえ、これらのことは悪い考えです。

根本的な問題は合成性です。すべてのOO言語と同様に、C++ではユーザー定義の型を使用できます。これらのタイプには、異なるタイプのメンバーを含めることができます。そして、C++は、そのような作成された型がどのように作成され破壊されるかの規則を定義します。

C++ルールは例外を考慮して記述されています。彼らはではありません。は、ゾンビオブジェクトを念頭に置いて書かれています。メンバーの作成時の例外は伝播され、その兄弟は適切に破棄されます。メンバーのゾンビ状態はではなく、は伝播せず、兄弟姉妹は(もしあれば)掃除が難しいです。

C++ルールに頼るのではなく、コンポジットオブジェクトにすべてのメンバーをチェックするbool isZombie() constメソッドが必要な会社単位のコーディング規格を導入することができます。しかし、C++にはテンプレートコンテナがあります。 std::vector<YourClass>ではなく、isZombie()メソッドを持ちます。 std::vector<>は、貴社のコーディング基準に準拠していません。ただし、std::vector<T>です。T::T()から例外が伝播します。そして、そうすると、内部状態を壊すことはありません。 vector.resize()の途中でさえも。

関連する問題