0

私は最近、

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番目の例は、もう少し意味があります。copyconstは使用されていないため、構築後に割り当てるだけです。

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

FooClass a = someObject.someMethodReturningFooClassInstance();

FooClass a(someObject.someMethodReturningFooClassInstance());?

ムチョスありがとう!

4

6 に答える 6

4

どちらの場合も違いはないと思います。同じコピーコンストラクターが両方とも呼び出されます。

これがまさにあなたがあなたのコードに書いたものであると確信していますか?

于 2009-01-02T12:10:43.510 に答える
2

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

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

于 2009-01-02T12:14:44.623 に答える
1

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

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

デバッガーで実行してみましたか?ABORT信号で中断​​する必要があります。

于 2009-01-02T12:13:59.837 に答える
0

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

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

SomeClass someObject;
mysqlpp::StoreQueryResult result;
result = someObject.getResult();
于 2009-01-02T12:15:42.203 に答える
0

実際には、最初のものは operator= を使用して中間コピーを実行し、2 番目のものは直接コピー構造を実行します。

于 2009-01-02T12:16:08.817 に答える
0

オブジェクトに値(正しい値)を代入するのが1つ目のケースだと思います。オブジェクトに値を送るのです。

于 2009-01-02T15:19:17.543 に答える