質問

最近、そうするコードを書きました

SomeClass someObject;
mysqlpp::StoreQueryResult result = someObject.getResult();

SomeClass :: getResult()は次のようになります:

mysqlpp::StoreQueryResult SomeClass::getResult()
{
mysqlpp::StoreQueryResult res = ...<something>...;
return res;
}

最初のコードスニペットの例を使用して、コンパイルして実行すると、プログラムはABORTシグナルでクラッシュしました。次に、最初のスニペットを次のように変更しました。

SomeClass someObject;
mysqlpp::StoreQueryResult result(someObject.getResult());

これはうまくいきました。また、試してみるために、もう一度次のように変更しました。

SomeClass someObject;
mysqlpp::StoreQueryResult result;
result = someObject.getResult();

これも正常に機能しました。

今、最初の例が失敗し、次の2つが成功した理由がわかりません。私が理解するように、最初の例では、結果を初期化するためにコピーコンストラクターが使用されます。しかし、これは2番目の例にも当てはまりませんか?では、なぜ2番目の例が成功したのでしょうか? 3番目の例はもう少し理にかなっています-copy constは使用されないので、構築後に割り当てるだけです。

要するに、次の違いは何ですか:

FooClass a = someObject.someMethodReturningFooClassInstance();

and

FooClass a(someObject.someMethodReturningFooClassInstance());?

Muchosありがとう!

役に立ちましたか?

解決

2つのケースに違いはないと思います。同じコピーコンストラクターが両方とも呼び出されます。

これは、コードで書いたものと正確に確かですか?

他のヒント

厳密に言えば、最初のケースではデフォルトのコンストラクターが呼び出され、その後に代入演算子が続き、2番目のケースではコピーコンストラクターのみが使用されます。

さて、私の最初の仮定は間違っていて、明らかにどちらの場合でもコピーコンストラクターだけが呼び出されます(割り当ての場合は、追加の「変換」コンストラクターも呼び出されます)。しばらくスリープした後にコンパイラを起動し、開発環境でこれを確認します。

コピーコンストラクター内にブレークポイント(またはprintfステートメント)を入れるだけで、いつ呼び出されたかを正確に知ることができます。基本的なデバッグを置き換えることはできません。 ;)

しかし、はい、コピーコンストラクターは最初の2つの場合に呼び出す必要があります。 3番目のケースでは、代わりに代入演算子を使用します。

デバッガで実行してみましたか? ABORTシグナルで中断します。

まあ、最初のものはoperator =で中間コピーを行い、2番目のものは直接コピー構成を行います。

最初のケースはオブジェクトに値(正しい値)が割り当てられていると思います。オブジェクトに値を送信します。2,3では、暗黙的なオブジェクトと明示的なオブジェクトの概念があります。 p>

最も純粋な理論では、どちらの場合でもコピーコンストラクターを呼び出す必要があります。 ただし、これらの場合にコンパイラーが使用できるReturn Value Optimization(RVO)と呼ばれるものがあります。 RVOを使用する場合、コピーコンストラクターは呼び出されません。おそらく、コンパイラーはRVOを1つのケースで使用し、他のケースでは使用しませんか?

編集: これはケースにのみ適用されます

SomeClass someObject;
mysqlpp::StoreQueryResult result;
result = someObject.getResult();
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top