121

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

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

3行目がを印刷し、constructor Foo7行目がエラーを返し、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;
}
4

3 に答える 3

143
   /* 1 */ Foo* foo1 = new Foo ();

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

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

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

   /* 3 */ Foo foo3;

自動ストレージでFoo呼び出されるオブジェクトを作成します。foo3

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

コピー初期化を使用して、自動ストレージでFoo呼び出されるオブジェクトを作成します。foo4

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

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

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

以前と同じ。

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

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

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

bar37で宣言されていない場合は、5と6と同じ原則で機能します。

5と6にはメモリリークが含まれています。

likeの構文new Bar ( Foo::Foo() );は通常ではありません。通常はnew Bar ( (Foo()) );-余分な括弧は、最も厄介な解析を説明します。(修正)

于 2012-09-03T13:24:34.420 に答える
24
  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
于 2012-09-03T14:19:49.847 に答える
5

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

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

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

于 2012-09-03T13:25:42.313 に答える