2016-11-27 7 views
-1

これはちょっと錆びています。私はオブジェクトの宣言、値と参照、スタックとヒープで何が起こるかを正確に把握しようとしています。私は基本を知っているが、以下の例については不明な点が午前:私はMyObject[] myObjArr1 = new MyObject[10]()を持っている場合スタック上のC++の構造体と配列、ヒープ、値、参照、参照解除の質問

struct MyObject 
{ 
    int foo; 
    MyObject(int val) 
    { 
     foo = val; 
    } 

    MyObject()//[EDIT] default constructor 
    { 
    } 
} 

//... 

//1) 
//this reserves memory on the stack for MyObject0 and initializes foo: 
MyObject a = MyObject(1); //[EDIT] fixed from comments 

//2) 
MyObject* b = new MyObject(2);//This I know reserves memory on the heap, 
//returns a pointer to it (and calls constructor). 
//There are also other ways like malloc or memset. 

//3) 
MyObject c = *(new MyObject(3));// So here we instantiate MyObject on the heap, 
//return a pointer to it but the pointer is dereferenced outside the parenthesis. 
//Is c now a newly created value type copy on the stack? 
//And is the original new MyObject(3) now inaccessible in the heap memory (leaked) 
//because the pointer to it was never stored? 

//4) 
// void myFunc(MyObject c){} 
myFunc(c); //Am I doing a member-wise assignment from c to a new function-scope 
//temporary MyObject reserved somewhere else in memory (in a stack frame?)? 
//Or am I somehow passing a reference to c even though c is not a pointer or reference? 
//[EDIT] myFunc(c); would pass as a reference if I had void myFunc(MyObject &c){} 

最後に、私は10の、初期化されていないMyObjectにヒープ上の構造体、およびヒープ上のタイプMyObject配列のポインタとしてもを持っています。

配列内のMyObject構造体もスタック上にあるMyObject配列をスタック上に宣言するにはどうすればよいですか?それともあなたがしていることではありませんか?

+0

**(1)** 'MyObject'にはデフォルトのコンストラクタがないので、' MyObject a; 'はコンパイルされません。 * "ここでもデフォルトのコンストラクタが呼び出されていますか?" **(2)**と**(3)**のあなたの結論は正しいです。 **(4)** 'myFunc'のパラメータは' c'からコピー初期化されます。 'MyObject'にはユーザ定義のコピーコンストラクタがないので、コンパイラが生成したものは実際にメンバごとのコピー初期化を実行します。 –

+0

@ Tudor、行MyObjectを行います。コンパイル?あなた自身のコンストラクターを定義して以来、デフォルトのコンストラクターを使用できないようにすべきではありません。 – feldi

+0

あなたは正しいです。これは、コンストラクタが定義されていない場合にのみコンパイルされます。 – Spectraljump

答えて

1

は、より正確な方法で、私は再びコメントしてみましょう:

1)これは一時的なMyObject(1)の値で初期化スタック上a変数を作成し、それをMyObjectMyObject::MyObject(1)を呼び出すと、スタック上に作成されますコンストラクタとして。コンパイラは、中間ステップを排除する可能性があります。あなたはそれを単にMyObject a(1);注を行うことができます。=が割り当て )MyObject::MyObject(2)を呼び出すことにより、ヒープ上MyObjectを作成し、それへのポインタを返し、bポインタを初期化に使用できません。彼らはメモリを割り当てますが、 CONSTRUCTオブジェクトはありません:

mallocmemset忘れてください。すぐにあなたはそれらを忘れてしまうでしょう。あなたにとってはより良いでしょう。 と他の誰か。

3)Myobjectがヒープ上に作成され、Myobkect::Myobject(3)を呼び出すことによって構成され、その後、newポインタを戻した間接参照し、得られた値をコピーすることによってcを初期化するために使用されます。ヒープ上に作成されたオブジェクトは、そこでは "忘れられています"。 (メモリリーク:あなたはさらにそれにアクセスする機会を持っていない)

4)オブジェクトcmyFuncのローカルパラメータcにコピーされます(実際には2 cは、二つの異なるオブジェクトである)までのスタックに存在すること関数は終了します。

+1

'MyObject a(1);'の説明のための小道具。削除可能な一時的な値、および新しい値によって構築された値。 – Spectraljump

関連する問題