1

私はいくつかのコードを書いたばかりで、オブジェクトがどのようにポリモーフィックに破壊されるかを理解しようとしています。

#include <iostream>

struct Base {
    virtual ~Base() {
        std::cout << "base destructed\n";
    }
};

struct Derived : public Base{
virtual ~Derived() {
    std::cout << "derived destructed\n";
}
};

int main() {
  Derived der;
  Base bases1[2], bases2[2], bases3[2], bases4[2];
  //case 1
  new(bases1) Derived(der);
  std::cout << "((Base*)bases1)->~Base();\n";
  ((Base*)bases1)->~Base();
  //case 2
  new(bases2) Derived(der);
  std::cout << "\nbases2->~Base();\n";
  bases2->~Base();
  //case 3
  new(bases3) Derived(der);
  std::cout << "\nbases3[0].~Base();\n"; 
  bases3[0].~Base();
  //case 4
  new(bases4) Derived(der);
  std::cout << "\n(*bases4).~Base();\n";    
  (*bases4).~Base();

  getchar();
  return 0;
}

上記のコードについて私が知っていること:

  1. ケース 1 では、bases1 は Derived オブジェクト (vptr を含む) の先頭を指し、これはベース ポインターであるため、ベース ポインターで削除する通常のケースと同じです (つまり、破棄)。
  2. ケース 2 では、bases2 は配列名ですが、場合によっては最初のオブジェクトを指すポインターとして扱うことができるので、ケース 2 はケース 1 と同じ結果になるはずですか?
  3. ケース 3 とケース 4 は同じです。どちらも、タイプが Base の最初のオブジェクトを逆参照してから、そのデストラクタを呼び出します。
  4. これらのコードは非標準で危険ですが、特定のコンパイラ (Visual Studio 2012) でどのように機能するかを知りたいだけです。

出力:

((Base*)bases1)->~Base();
derived destructed
base destructed

bases2->~Base();

bases3[0].~Base();
base destructed

(*bases4).~Base();
base destructed

私が知りたいこと:

  1. ケース 2 では、何も破壊されません。考えられる理由は何ですか? コンパイラの最適化?
  2. ケース 3 とケース 4 では、ベースのみが破壊されますが、なぜですか? オブジェクトのスライス?

編集:

以下は、[逆アセンブリ] ウィンドウから取得したものです。

 ((Base*)bases1)->~Base();
00D96CF9  mov         esi,esp  
00D96CFB  push        0  
00D96CFD  mov         eax,dword ptr [bases1]  
00D96D00  lea         ecx,[bases1]  
00D96D03  mov         edx,dword ptr [eax]  
00D96D05  call        edx  
00D96D07  cmp         esi,esp  
00D96D09  call        __RTC_CheckEsp (0D91992h)

  bases2->~Base(); //empty

  bases3[0].~Base();
00D96DB0  push        0  
00D96DB2  mov         eax,4  
00D96DB7  imul        eax,eax,0  
00D96DBA  lea         ecx,bases3[eax]  
00D96DBE  call        Base::`vector deleting destructor' (0D91A0Ah) //array delete?

  (*bases4).~Base();
00D96E14  push        0  
00D96E16  mov         eax,4  
00D96E1B  imul        eax,eax,0  
00D96E1E  lea         ecx,bases4[eax]  
00D96E22  call        Base::`vector deleting destructor' (0D91A0Ah)  //aray delete?

アセンブラが読めないのですが、どなたか合理的な説明をいただけないでしょうか?

4

1 に答える 1