3

次のようなコードがあります。

ComplexObject cpy;
{
  RAIILockObject _(obj->mutex);
  cpy = obj->org;
}
// use cpy

議論のために、のデフォルトコンストラクタComplexObjectはコストがかかると仮定します。

  • C ++コンパイラはcpyのデフォルトの構築/割り当てをコピーコンストラクタに置き換えることができますか(そしてできますか)?
  • 両方のローカルオブジェクトのスコープを維持しながら、その最適化を強制するようにコードを再構築する方法はありますか?

編集:私は、RAIIオブジェクトを他のものと不適切にネストしたいという問題の一般的な解決策を本当に探しています。

コンラッド・ルドルフの解決策についてのコメントはありますか?

ComplexObject = LockedInitInPlace(obj->org, obj->mutex);

template<class C> C LockedInitInPlace(C& c, Mutex& m) {
    RAIILockObject _(m);
    return c;
}

編集2:

元のコードには次のシーケンスがあります。

  1. デフォルトの構成cpy
  2. RAIIを構築するlock
  3. 既存のオブジェクトをに割り当てる(コピーする)cpy
  4. 破壊するlock
  5. 使用するcpy
  6. 破壊するcpy

私が欲しいのは:

  1. RAIIを構築するlock
  2. コンストラクトcpy(この場合、既存のオブジェクトを使用したコピーコンストラクターによる)。
  3. 破壊するlock
  4. 使用するcpy
  5. 破壊するcpy
4

3 に答える 3

3

C++コンパイラは、cpyのデフォルトの構築/割り当てをコピーコンストラクタに置き換えることができますか?

いいえ、コンパイラーはこれを行うことを禁じられています (クラスのデフォルトのコンストラクターが十分に複雑であり、その省略が同等のプログラムになることをコンパイラーが証明できないと仮定します)。標準に準拠していないコンパイラ。

編集:次の解決策には欠陥があります! 使用しないでください。

次の解決策は、競合状態を隠します。あなたのロックがクリティカル セクションでコピーが行われることを保証するものであった場合、コピーはこのクリティカル セクションの外で行われる可能性が高い (おそらくそうなる) ため、私の「解決策」はこの仮定を破ります。他の仕事をしている場合にのみ機能します。ただし、元のコードでは、コピー自体が重要な場合にのみミューテックスが意味をなします。

デフォルトの構築を防ぐには、次のようにします。

ComplexObject = init(any_params_here);

ComplexObject init(any_params_here) {
    RAIILockObject _(obj->mutex);
    return obj->org;
}

コピー省略のおかげで、これは不要なコピーさえ実行せず、1 つだけ実行します (コードのように、コピー割り当てではなく直接コピーとして)。

于 2011-07-20T16:11:34.600 に答える
3

そのような最適化が同じ動作になることをコンパイラが証明できない限り、いいえ。(ミューテックスロックを考えると)コンパイラがこれを行うことができるケースを本当に想像することはできません。

これは当たり前のように聞こえるかもしれませんが、コストがかからないようにデフォルトのコンストラクターを変更できますか? このようなコンストラクターは、誤って呼び出しやすい場合、他の場所でパフォーマンスの問題を引き起こす可能性があります。

または、ローカル インスタンスではなく、ヒープとポインター (コピー コンストラクトの作成を介して) を使用する必要があります。

std::scoped_ptr<ComplexObject> cpyPtr = 0;
{
  RIAALockObject _(obj->mutex);
  cpyPtr = new ComplexObject(obj->org);
}
ComplexObject& cpy = *cpyPtr;  // create alias for ease of use.
于 2011-07-20T15:58:34.113 に答える
3

コンストラクターが複雑な場合、既定のコンストラクターが回避される可能性はほとんどありません。

コンパイラは、プログラムの観察可能な動作が損なわれない限り、ほとんど何でも実行できます。

この問題を解決する最善の方法は、デフォルトのコンストラクターをComplexObject高価にしないことです。まさにこの理由から、高価なデフォルト コンストラクターを使用することはお勧めできません。

于 2011-07-20T16:00:07.800 に答える