2011-07-19 12 views
10

私はC++のチュートリアルを読んでいますが、実際には両者の違い(構文以外)はありませんでした。ここにチュートリアルの引用があります。明示的代入と暗黙的代入

宣言時に変数に値を割り当てることもできます。私たちは、代入演算子を使用して変数に値を代入 とき( 等号)、それは明示的な割り当てと呼ばれています:

int nValue = 5; // explicit assignment 

また、暗黙的な割り当てを使用して変数に値を割り当てることができます。

int nValue(5); // implicit assignment 

暗黙的な代入は関数呼び出しとよく似ていますが、 コンパイラは、どの名前が変数であり、どれが正しく解決できるように関数が であるかを把握しています。

違いはありますか?もう一方の方がより好ましいのですか?

+5

これは宣言ではなく、定義です。そのチュートリアルと[まともな本を読む](http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list)を捨てなさい。 C++で考えることは無料で、著者のページから入手できます。 –

+3

@Cat Plus Plus:定義ですが、宣言ではありません。 –

+1

@JamesMcNellis:それはチュートリアルであり、呼び出し定義宣言は2つの間の混乱を取り除くのに役立つものではありません。多分私は今日は気難しいです。 :P –

答えて

10

intのようなプリミティブ型のほうが優先されます。コンストラクタが呼び出されるため、2番目のコンストラクタはコンストラクタを持つ型を持ちます。

例えば、あなたは、単一のintから構成することができるclass Fooを定義した場合

Foo x(5); 

Foo x = 5; 

好まれるよりも多くの場合は、その後、(あなたがとにかく旧構文を必要としますあなたがoperator=が呼び出されているように見えて、Foo x = Foo(5, "hello");を普通に使っていない限り、1つの引数が渡されます。

+4

これは、構文を構文解析すると、ほとんどの厄介な構文解析に注意する必要があることに言及します。 –

+4

'Foo x = 5'は' Foo :: Foo(int) 'が' explicit'とマークされていないと動作しません。 – Vitus

+0

...(@Vitusコメントを続けます)と 'Foo'コピーコンストラクタにアクセスできます。 –

1

変数を宣言して初期化するとき、そのコンテキストでは機能的に同じです。私は通常通り2を参照してください。それがより自然であるため、基本的なタイプでは

int nValue = 5; // assignment syntax 

int nValue(5); // construction syntax 

、私は特に他の言語でプログラミングしている人のために、建設を超える割り当てを好みます。

クラス型の場合、コンストラクタ関数の存在を避けるため、構文を使用することをお勧めします。

+1

標準(N3242)は 'T x = a' * copy-initialization *と' T x(a) '* direct-initialization *という構文を呼び出します。どちらもコンストラクタ 'T :: T(a)'を呼び出す有効な方法です。 –

5

プリミティブ型はどちらも同等ですが、それはユーザー定義のクラス型の違いがあります。どちらの場合も、実行されるコードは(基本的な最適化が実行された後に)同じになりますが、初期化元の要素が構築している要素でない場合、型の要件が異なります。

コピー初期T t = u;)暗黙tuから変換されたタイプTの一時から構造をコピーすることと等価です。一方、直接初期化は、適切なコンストラクタへの直接呼び出しに相当します。

uを取るコンストラクタがexplicit宣言されているかコピーコンストラクタにアクセスできない場合は、コピー初期化が失敗した場合、ほとんどの状況で、何の違いもないだろうが:

struct A { 
    explicit A(int) {} 
}; 
struct B { 
    B(int) {} 
private: 
    B(B const &); 
}; 
int main() { 
    A a(1);  // ok 
    B b(1);  // ok 
// A a2 = 1; // error: cannot convert from int to A 
// B b2 = 1; // error: B(B const &) is not accessible 
} 

歴史的背景のなかには、最初にプリミティブ型をコピー初期化で初期化する必要がありました。クラスのメンバ属性を初期化するために* initializer-list *が言語に追加されたとき、初期化子リスト内の構文を統一的かつ単純に保つために、プリミティブ型をクラスと同じ構文で初期化する必要があると判断されました。同時に、コピー初期化によってクラスの初期化を可能にするは、プリミティブ型に近いユーザー定義型を作成します。 2つの初期化形式の違いは当然です。int a = 5.0;は、5.0からintへの変換として処理された後、intからaの初期化に処理されます。 T u = v;vからTへの変換として処理され、その変換された値からuのコピー構成がコピーされます。

関連する問題