2017-05-14 7 views
1

私の質問は実際には2つの部分から成っています。早い序文:私はC++を学んでおり、C#/ .NETのバックグラウンドから来ています。現在、オブジェクトの存続期間を理解しようとしていますが、以下に掲載されている結果は意味をなさないものです。私はそれが匿名のインスタンスの作成と関係があると思いますか?オブジェクトの構成、寿命、破壊の理解

質問1:デストラクタのすべてのメンバーを「空のオブジェクト」である可能性があるので処分することをお勧めしますか?

質問2:どうすればこの問題を防ぐことができますか? /この機能を使用するにはオブジェクトをどのように設計するのですか?

質問3:これは「正しい」/「正しい」方法ですか?

質問4:コード

#include <stdio.h> 

class A 
{ 
public: 
    A() 
    { 
     printf("Constructor A\n"); 
    } 

    ~A() 
    { 
     printf("Destructor A\n"); 
    } 
}; 

class B 
{ 
public: 
    B() 
    { 
     a = A(); 

     printf("Constructor B\n"); 
    } 

    ~B() 
    { 
     printf("Destructor B\n"); 
    } 
private: 
    A a; 
}; 

int main(int argc, char* argv[]) 
{ 
    B b; 
    b = B(); 

    printf("Done"); 
    // Breakpoint 
    /* 
     Output: 

     Constructor A 
     Constructor A 
     Destructor A 
     Constructor B 
     Constructor A 
     Constructor A 
     Destructor A 
     Constructor B 
     Destructor B 
     Destructor A 
    */ 
} 

そして、私が現在働いているプロジェクトから来ている他の例の非常に最後のビットにコメントを参照してください。

#include <stdio.h> 

class Mesh 
{ 
public: 
    Mesh() 
    { 
     printf("Constructing Mesh with data %d\n", data); 
    } 

    Mesh(int d) 
    { 
     data = d; 

     printf("Constructing Mesh with data %d\n", data); 
    } 

    ~Mesh() 
    { 
     printf("Destructing Mesh with data %d\n", data); 
    } 

private: 
    int data = 0; 
}; 

class Game 
{ 
public: 
    Game() 
    { 
     printf("Game constructor\n"); 
    } 

    ~Game() 
    { 
     printf("Game destructor\n"); 
    } 

    void init() 
    { 
     int cool_data = 3; 

     mesh = Mesh(cool_data); 
    } 

private: 
    Mesh mesh; 
}; 

int main(int argc, char* argv[]) 
{ 
    Game game = Game(); 
    game.init(); 

    printf(""); 
    // Breakpoint 
    /* 
     Output: 

     Constructing Mesh with data 0  <-- I assume this comes from the private member declaration in the Mesh class? So declaration means initialization? 
     Game constructor 
     Constructing Mesh with data 3  <-- Okay that's what I expected since I'm creating a new instance of the Mesh class with "3" passed in 
     Destructing Mesh with data 3  <-- Why is the instance we JUST created immediately being destructed? 
    */ 
} 
+2

「これがどうして起こるの? ??? –

+2

^- つまり、これは* this *ですか? – StoryTeller

+1

@JohnZwinck私の投稿を少し編集しました。もっと情報が必要な場合はお知らせください:) – mskc33

答えて

1

最初の例では、C++に慣れていないと謎のように見える "A"オブジェクトの構築と破棄が多く見られます。あなたのBクラスは私的な変数 "a"を持っています。このオブジェクトは、最初にBクラスにコンストラクタを呼び出すと、デフォルトで構築されます。これはあなたが見る最初の "コンストラクタA"のプリントアウトです。クラスAのデフォルトコンストラクタの呼び出しによって返されたR値に「A」、クラスAのすでにインスタンス化されたオブジェクトを、割り当て

B() 
{ 
    a = A(); //A() calls the A constructor and returns an r-value 
    printf("Constructor B\n"); 
} 

:次のプリントアウトは、ここではAのコンストラクタの呼び出しからですr値が作成されたときに「コンストラクターA」を、r値自体が破棄されたときに「デストラクターA」を出力します。これらの動作はコピーと移動のコンストラクタ/演算子を作成することで変更できます。これにより、これらのセマンティクスの動作方法を指定できます。これらの操作の詳細については、http://www.cprogramming.com/c++11/rvalue-references-and-move-semantics-in-c++11.htmlまたは本(C++ 11入門書)を参照してください。あなたが作成したBオブジェクト「b」はに割り当てるときにBクラスのデフォルトコンストラクタのはラインで右辺値を返さ上記のロジックに続い

、:

b = B(); 

あなたがしなければならない 1新しいBオブジェクトを構築)構築オブジェクト 2)を作成するr値 3)破壊r値 4)を構築Bの最後の2つの印刷ステートメントは単にBオブジェクトが主出口として破壊されている

オブジェクト。 Bオブジェクトは破壊され、そのメンバーAオブジェクトも破壊されます。あなたの最初の質問は、この動作についてのようです。クラスメンバーを手動で破壊するかどうかを尋ねているようです。あなたのクラスがメンバーにメモリを割り当てる場合、これはC++でのみ行われます。

B() 
{ 
    a = new A(); 
    printf("Constructor B\n"); 
} 
... 
private: 
A* a; 

は、その後、あなたのデストラクタでこのA *の割り当てを解除する必要があります:場合は、例えば、代わりにローカルオブジェクトを作成するので、Bであなたのコンストラクタはこれをしませんでした。 new演算子を使用して新しいメモリを割り当てていない限り、C++は他のすべての解放を処理します。

あなたの質問2と3は、オブジェクトの構築を防止する方法と、オブジェクトの構築/破壊の方法が正しいかどうかについてです。私はあなたに0/3/5のルールを指摘したいと思います。これは、基本的に、与えられたクラスに対して作成するコンストラクターの数を扱います。これは、ルールhttp://en.cppreference.com/w/cpp/language/rule_of_threeのかなり簡単な説明ですが、他にも多くのオンラインがあります。

あなたの最後の質問は、あなたが持っているメッシュクラスと、なぜあなたの変数の1つが破壊されているのかです。ここでも、これはコンストラクタの呼び出しによって返されたr値と関係があります。あなたのメッシュのコンストラクタを呼び出し、自分の変数にその戻り値を割り当てるとき基本的に、ここでは「メッシュ」:

void init() 
{ 
    int cool_data = 3; 
    mesh = Mesh(cool_data); 
} 

メッシュコンストラクタは、クラスのオブジェクトが3のデータ値をメッシュであるr値を返します。 r値は "メッシュ"変数にコピーされ、即座に破棄され、 "メッシュ"変数はその正確なコピーとして残ります。ここでも、適切なコンストラクタと演算子を作成することによって、これらの動作すべてを変更できます。

+0

絶対に恒星の返信。ありがとうございました! – mskc33

関連する問題