7

「C++入門書」を読んでいます。オブジェクトの初期化では、C++ は直接とコピーの 2 つの形式の初期化をサポートしています。しかし、本は参照の初期化を参照していません。そして本では、参照の直接初期化(存在する場合)を見たことがありません。すべては次のようなコピーです。

int i;
int &j = i;//but not int &j(i);which also works in my experiment

参照の初期化のために下で行われているのと同じであることを知りたいです。次のコードの場合:

string null_book = "9-999-99999-9";

初期化の進行状況は、最初に ac スタイルの文字列パラメーターで直接初期化される一時的な文字列オブジェクト tmp (たとえば) を作成し、次にコピー コンストラクターで変数 null_book を初期化することです。それは私には理にかなっています。これについて:

int &j = i;

ref j は同じように初期化されますか? それは一時参照になります &t (たとえば) i で初期化され、j を t で初期化しますか? それは意味がありませんか?なぜこの本は参照のために直接初期化を使用しないのですか? ご清聴ありがとうございました!

4

3 に答える 3

7

直接初期化とコピー初期化の主な違いは、標準のセクション 8.5、パラグラフ 17 で説明されています。一般に、違いは、コピー初期化のクラス型の場合、明示的なコンストラクターは考慮されず (変換コンストラクターのみが考慮されます)、省略される可能性のあるコピーが作成されることです。直接初期化では、明示的なコンストラクターが考慮され、ターゲットが直接構築されます。標準のセクション8.5から:

=[... ]

非クラス型 (参照を含む) の場合、直接初期化とコピー初期化のセマンティクスは似ています。参照の場合、 8.5.3 参照 [dcl.init.ref]で指定されているように、どちらの場合でも参照バインディングが発生します。参照の直接初期化とコピー初期化は、変換関数が関与する場合にのみ異なるセマンティクスを持ちます ( 13.3.1.6 直接参照バインディングの変換関数による初期化 [over.match.ref] )。繰り返しますが、直接初期化は、コピー初期化が許可されていない明示的な変換関数を呼び出すことができます。

だから、

int &j = i;

8.5.3p5 が適用され、参照jは lvalue に直接バインドされiます。一時的なものは呼び出されません。

複雑さという点では、参照はクラス型よりも基本 (プリミティブ) 型に近いです。プリミティブは一時的に構築されることなく初期化され (8.5p17、最後の箇条書き)、一般的に参照も同様です。これがおそらく、この本が=参照の初期化にのみフォームを使用する理由です。プリミティブの場合と同様に、通常は違いはなく、書き込みint i = x;は通常 よりも明確ですint i(x);

于 2012-12-19T13:03:55.897 に答える
4

コピー初期化および直接初期化という用語は、C++の文法の一部です。どのようなコード生成が行われるかはすぐにはわかりません。文法構造の意味は標準で記述されており、初期化のコンテキストでは、初期化されるもののタイプに応じて、さまざまな特定の結果があります。

特に、プリミティブ型、ポインター型、および参照型の場合、直接初期化とコピー初期化(文法構造!)の両方がまったく同じ効果を持ちます。つまり、基本型とポインター型は初期化子の値で初期化され、参照は初期化子によって参照されるオブジェクトにバインドされます。

int a1 = 5;
int a2(5);      // same thing

Foo * p1 = &x;
Foo * p2(&x);   // same thing

Bar & b1 = y;
Bar & b2(y);    // same thing

(ただし、ユーザー定義型の場合、直接初期化とコピー初期化には違いがありますが、通常は重要ではない微妙なものです。)

于 2012-12-19T13:08:29.353 に答える
3

C++ での参照は、変な帽子をかぶった単なるポインターです。ステートメント:

TYPE& x = y;

は常に次と同等です。

TYPE* const x = &y;

すべての参照が行うことは、*文字を入力する手間を省き、null が存在しないという信念を宣言することです。したがって、初期化はオブジェクトではなくポインターの初期化であり、一時的であろうとなかろうと、処理するオブジェクトの複雑さがないため、簡単です。

これは概念モデルです。もちろん、最適化があります。次のような関数を宣言すると:

void takeARef(FOO const& ref) { ... }

それを呼び出すと、コンパイラはポインタを関数に渡すだけで、何も作成しません。

于 2012-12-19T12:58:15.520 に答える