web-dev-qa-db-ja.com

クラスのインスタンスを作成する

行1、2、3、4の違いは何ですか?

それぞれをいつ使用しますか?

3行目がconstructor Fooを出力し、7行目がエラーを返し、8行目がエラーを返さないのはなぜですか?

#include <iostream>     
using namespace std;

class Foo
 {
   public:
   Foo ( )
   {
      cout << "constructor Foo\n";
   }               
};

class Bar
 {
   public:
   Bar ( Foo )
   {
      cout << "constructor Bar\n";
   }
};

int main()
{
   /* 1 */ Foo* foo1 = new Foo ();
   /* 2 */ Foo* foo2 = new Foo;
   /* 3 */ Foo foo3;
   /* 4 */ Foo foo4 = Foo::Foo();

   /* 5 */ Bar* bar1 = new Bar ( *new Foo() );
   /* 6 */ Bar* bar2 = new Bar ( *new Foo );
   /* 7 */ Bar* bar3 = new Bar ( Foo foo5 );
   /* 8 */ Bar* bar3 = new Bar ( Foo::Foo() );

   return 1;
}
88
Kolyunya
   /* 1 */ Foo* foo1 = new Foo ();

動的メモリにタイプFooのオブジェクトを作成します。 foo1はそれを指します。通常、C++では生のポインターを使用するのではなく、スマートポインターを使用します。 FooがPODタイプの場合、これは値の初期化を実行します(ここでは適用されません)。

   /* 2 */ Foo* foo2 = new Foo;

FooはPODタイプではないため、以前と同じです。

   /* 3 */ Foo foo3;

自動ストレージにfoo3というFooオブジェクトを作成します。

   /* 4 */ Foo foo4 = Foo::Foo();

コピー初期化を使用して、自動ストレージにfoo4というFooオブジェクトを作成します。

   /* 5 */ Bar* bar1 = new Bar ( *new Foo() );

Barの変換コンストラクターを使用して、動的ストレージにタイプBarのオブジェクトを作成します。 bar1はそれへのポインタです。

   /* 6 */ Bar* bar2 = new Bar ( *new Foo );

前と同じ。

   /* 7 */ Bar* bar3 = new Bar ( Foo foo5 );

これは単なる無効な構文です。そこで変数を宣言することはできません。

   /* 8 */ Bar* bar3 = new Bar ( Foo::Foo() );

7でbar3が宣言されていなかった場合、5および6と同じ原理で動作し、動作します。

5&6メモリリークが含まれます。

new Bar ( Foo::Foo() );のような構文は普通ではありません。通常はnew Bar ( (Foo()) );です- ほとんどのベキシング解析のための追加の括弧アカウント。 (修正済み)

109
Luchian Grigore
  1. 空きストアからいくつかの動的メモリを割り当て、デフォルトのコンストラクタを使用してそのメモリにオブジェクトを作成します。削除しないため、メモリがリークします。
  2. 1とまったく同じです。ユーザー定義型の場合、括弧はオプションです。
  3. 一部の自動メモリを割り当て、デフォルトのコンストラクタを使用してそのメモリにオブジェクトを作成します。オブジェクトがスコープ外になると、メモリは自動的に解放されます。
  4. 3と同様に、名前付きオブジェクトfoo4は、デフォルトで一時オブジェクトの構築、コピー、および破棄によって初期化されます。通常、これは省略され、3と同じ結果になります。
  5. 動的オブジェクトを割り当て、最初のオブジェクトをコピーして2番目のオブジェクトを初期化します。両方のオブジェクトがリークされています。そして、あなたはそれへのポインタを保持しないので、最初のものを削除する方法はありません。
  6. 5とまったく同じです。
  7. コンパイルしません。 Foo foo5は宣言であり、式ではありません。関数(およびコンストラクター)引数は式でなければなりません。
  8. 一時オブジェクトを作成し、動的オブジェクトをコピーして初期化します。動的オブジェクトのみがリークされます。一時式は、完全な式の最後に自動的に破棄されます。同等のFoo()(または実際にはFoo::Foo())ではなく、Foo::Foo::Foo::Foo::Foo()だけで一時ファイルを作成できることに注意してください。

それぞれをいつ使用しますか?

  1. コードに不要な装飾が必要でない限り、そうしないでください。
  2. 現在のスコープよりも長持ちするオブジェクトを作成する場合。使い終わったら削除することを忘れないでください。そしてスマートポインターを使用してライフタイムをより便利に制御する方法を学んでください。
  3. 現在のスコープにのみ存在するオブジェクトが必要な場合。
  4. 3が退屈に見え、不必要な装飾を追加する必要があると思わない限り、しないでください。
  5. 回復のチャンスなしでメモリをリークするので、しないでください。
  6. 回復のチャンスなしでメモリをリークするので、しないでください。
  7. コンパイルしないでください。
  8. 一時的なBarから動的なFooを作成する場合。
18
Mike Seymour

行1、2、3、4はデフォルトのコンストラクターを呼び出します。それらは本質的に異なり、1,2は動的に作成されたオブジェクトであり、3,4は静的に作成されたオブジェクトです。

7行目では、引数呼び出し内にオブジェクトを作成します。エラーです。

また、5行目と6行目はメモリリークの誘因です。

5
Coding Mash