行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;
}
/* 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()) );
です- ほとんどのベキシング解析のための追加の括弧アカウント。 (修正済み)
foo4
は、デフォルトで一時オブジェクトの構築、コピー、および破棄によって初期化されます。通常、これは省略され、3と同じ結果になります。Foo foo5
は宣言であり、式ではありません。関数(およびコンストラクター)引数は式でなければなりません。Foo()
(または実際にはFoo::Foo()
)ではなく、Foo::Foo::Foo::Foo::Foo()
だけで一時ファイルを作成できることに注意してください。それぞれをいつ使用しますか?
Bar
から動的なFoo
を作成する場合。行1、2、3、4はデフォルトのコンストラクターを呼び出します。それらは本質的に異なり、1,2は動的に作成されたオブジェクトであり、3,4は静的に作成されたオブジェクトです。
7行目では、引数呼び出し内にオブジェクトを作成します。エラーです。
また、5行目と6行目はメモリリークの誘因です。