0

私は何でも参照できるJavaから来ているので、c++インスタンスの作成の基本を理解しようとしています。

Employee getEmp(int a) {
    Employee local(a);
    return local;
}
Employee myEmp = m.getEmp(10);

従業員のインスタンス化が3回ある(RVOなし)というのは正しいですか?
1-ローカルコピーを作成します
2-参照にバインドするために一時的に作成されます)
3-myEmpを作成します

ステップ2で必要なのはなぜですか?ローカルをmyEmpに直接コピーしないのはなぜですか?

Ubuntuのみを使用する場合、RVOを信頼する必要がありますが、RVOでは2つのインスタンスの作成のみが行われることを修正しますか(ステップ2では必要ありません)?

ありがとうございました!!!

4

2 に答える 2

3

なしRVO/NRVOで、copy elisionの呼び出しが1つとの呼び出しがEmployee(int)2つありcopy c-tor、1つはreturnのとき、もう1つはconstructのときmyEmpです。RVOおよび-c-torをコピーするためのcopy elision1回の呼び出し、およびおそらく0回の呼び出し。Employee(int)

copy elision別のオブジェクトから新しいオブジェクトを構築したいので、コピーコンストラクターの2回目の呼び出しは必須です(work to copy c-tor)。

于 2012-10-02T08:39:44.820 に答える
2

関数returnのセマンティクスは、戻り値の処理とは関係なく定義されます。戻り値は、ローカルスタックフレームが破棄されても消えない場所にコピーされます。したがって、RVOがない場合、あなたの例では、次のようになります。

  1. localのスタックフレームでの、という名前のローカル変数の構築getEmp

  2. 呼び出し元がアクセスできる場所に、返されたオブジェクトの構造をコピーします。通常、呼び出し元は、返されたオブジェクトに独自のスタックフレームでメモリを割り当て、このメモリのアドレスを含む非表示の引数を呼び出された関数に渡します。RVOまたはNRVOを使用すると、コンパイラはこの返されたオブジェクトをローカルオブジェクトに「エイリアス」できます。この場合、localローカルスタックフレームではなく、非表示の引数として渡されたアドレスに変数を作成します。

  3. 戻った後、返されたオブジェクトは「使用」され、完全な式の最後で破棄されます。 この使用法がコピーコンストラクターを使用してローカル変数を初期化することである場合、中間値は省略される可能性があります。コンパイラは、呼び出された関数に隠し引数として構築される実際のオブジェクトのアドレスを渡します。(厳密に言えば、これはNRVOではありませんが、関連しています。)ただし、他の用途を排除することはできません。たとえば、戻り値が既存の変数への代入で使用される場合、代入演算子は、代入されるインスタンスへの参照を必要とします。戻り値のほとんどの使用はコピーコンストラクターへの引数としてではないため、中間オブジェクトの正式な要件があります。

最後に、最新のコンパイラテクノロジを考えると、コンパイラが上記の2番目のコピーを体系的に排除することを期待できます。最初のコピー(RVOまたはNRVO)はやや難しいかもしれません。上記のような単純なケースでは、体系的に表示されると思います。RVOは、一時的なものが1回返されるときはいつでも、NRVOは、関数の最も外側のスコープで定義された名前付き変数を返す1回の返されるときはいつでもです。関数に複数の戻り値がある場合、NRVO(および実際にはRVOも、理由はわかりませんが)が発生する可能性は低くなります。

于 2012-10-02T09:39:52.157 に答える