2016-12-25 21 views
1

の破壊は我々が簡単な構造体があるとした後、基本クラスのメンバを使用:すべてのメンバーがプリミティブ型を持っているので、実装の観点から派生クラス

struct RefCounters { 
    size_t strong_cnt; 
    size_t weak_cnt; 
    RefCounters() : strong_cnt(0), weak_cnt(0) {} 
}; 

を、デストラクタRefCounters::~RefCountersは、何もしないはずです。これは、このタイプのオブジェクトがデストラクタの明示的な呼び出しで破棄された場合(そのメモリがではなく、が解放されている場合)、オブジェクトが正常に終了した後でメンバーと正常に作業できることを意味します。

は、今、私たちはRefCountersから派生し、いくつかのより多くのクラスを持っていると仮定します。 RefCountersが、基底クラスDerivedクラスの間に正確に1回存在するとします。デストラクタがクラスDerivedのオブジェクトに対して明示的に呼び出されたが、そのメモリがでなく、が割り当て解除されているとします。その後、メンバーstrong_cntweak_cntにアクセスできますか?実装の観点から

は、それが少なくとも関与なし仮想継承がない場合、[OK]をする必要があります。 Derived*は静的(アドレスにオフセットコンパイル時に定数を加算)RefCounters*にキャストすることができ、かつRefCountersのメモリがDerivedクラスのデストラクタが触れるべきではありませんので。ここで

は、コードサンプルです:

struct RefCounted : public RefCounters { 
    virtual ~RefCounted() {} 
}; 

struct Base : public RefCounted { 
    int val1; 
    virtual void print(); 
}; 

struct Derived : public Base { 
    std::string val2; 
    virtual void print(); 
}; 

Derived *pDer = new Derived(); 
pDer->~Derived();   //destroy object 
pDer->strong_cnt++;  //modify its member 
std::cout << pDer->strong_cnt << pDer->weak_cnt << "\n"; 

、このようなコードはC++標準で定義されていない動作と考えていますか?それがうまく動作しない理由がありますか?軽微な変更やいくつかの制約を加えて合法化することはできますか?

P.S.おそらく、そのようなコードサンプルでは、​​intrusive_ptr + weak_ptrのコンボを作ることができます。そのため、少なくとも1つのweak_ptrがまだポインタを指している場合、常にweak_ptrをオブジェクトポインタから得ることができます。詳細はthis questionを参照してください。

+0

関連のないメモでは、なぜ、 'RefCounters'はそのカウンタ自体を扱わないのですか?デストラクター*が何かを行う(つまり、一方または両方のカウンターを減らす)ことを意味しますか? –

+1

'RefCounters'は些細なデストラクタを持っているので、** [basic.life]/1 **ごとにストレージが再利用されたり解放されたりすると、そのライフタイムは終了します。明示的なデストラクタ呼び出しはノーオペレーションであり、何にも影響しません。 'RefCounters 'の特定のインスタンスがより大きなオブジェクトのサブオブジェクトであるという事実も考慮する必要はありません。 –

+0

@IgorTandetnik:ご意見ありがとうございます。私は最初のケース(すなわち、派生したクラスなし)で合法にするべきだと思います。しかし、派生クラスの2番目のケースについてはまだ分かりません。 – stgatilov

答えて

0

あなたのアプローチは悪いと思います。コメントには、標準の詳細について議論する素晴らしいリンクがあります。議論が行われると、異なるコンパイラがこの詳細を異なる方法で実装する可能性が高くなります。さらに。同じコンパイラでは、実装をあるバージョンから別のバージョンに変更する可能性があります。

より多くのあなたは、様々な暗いコーナーを使用し、大きなあなたが問題に会うチャンスです。

ボトムライン。達成しようとしていることは何ですか?通常のC++言語機能を使用してこれを行うことができないのはなぜですか?

+0

"P.S."質問のセクションでは、私はそこにリンクを追加しました。しかし、これは良い答えではないので、 "あなたはそれをしてはいけない"のようなものを投稿してはいけません。 – stgatilov

+0

@stgatilov、質問は "派生クラスを破棄してもまだ生きている基底クラス(とその**原始的な**データメンバー)"がスマートポインタを設計する方法の議論にはかなり関係していないので、 。 –

+0

"このコードが合法であるかどうか"、 "合法になるように変更できますか?"私のポイントは、このことについて委員会でさえ議論があるので、疑念は「違法」の方向にシフトすべきだということです。議論が解決され、コンパイラがこの解決に揃うまで、コードは少なくとも不正です。 –