1

大規模なプロジェクトを C++ Builder 2010 から XE4 に移植していて、このコードを見つけました。CB2010 でコンパイル、実行、動作したようです。リビジョン ログによると、C++ Builder 2007 をまだ使用していたときに追加されました。 これらのコンパイラはどちらも右辺値参照をサポートしていませんでした。

VOperandValue& VOperandValue::operator=(VOperandValue&& oOther) {
    // Assignment operator takes full control of all pointers etc, and sets oOther
    // to not own anything
    if (static_cast<void*>(this) != static_cast<void*>(&oOther)) {
        CopyAndTakeOwnershipFrom(oOther);
    }
    return *this;
}

void VOperandValue::CopyAndTakeOwnershipFrom(VOperandValue&& oOther) {
    // Lots of assignments to self's members, and clearing fields of oOther
}

2 つの注意事項:

  • operator=コピー元オブジェクトの変更は意図的なものです。このクラスは、一度に 1 つのオブジェクトのみが所有できるリソースをラップします。この質問の範囲を超えていますが、動作は奇妙ですが、設計どおりです。コピー コンストラクターと、同様に変更された他のいくつかのメソッドもあります。メソッドは、コピー元のオブジェクトが無効になる (破棄されるなど) か、新しいものを保持するために再利用される場合に使用することを目的としています。static_cast<void*>ポインターを同じタイプのオブジェクトと比較するために必要な理由がわかりません。私には、それは非常に奇妙なことのように思えます。
  • コードは、標準参照 (つまりVOperandValue& oOther) から右辺値参照に変更されました。右辺値参照のサポートは、C++Builder 2010 以降のバージョンである C++Builder XE にのみ追加されましたが、コンパイラは喜んでそれを受け入れてコンパイルし、コードは実行時に機能しているように見えました。

このコードが XE4 に読み込まれるCopyAndTakeOwnershipFrom(oOther)と、次のエラーでコンパイルに失敗します。

[bcc32 エラー] OperandValue.cpp(178): E2559 タイプ 'VOperandValue' の左辺値でタイプ 'VOperandValue' の右辺値参照を初期化できません

[bcc32 エラー] OperandValue.cpp(178): E2342 パラメーター 'oOther' の型が一致しません ('VOperandValue &&' が必要で、'VOperandValue' を取得しました)

CopyAndTakeOwnershipFrom(oOther);(178行目は行であり、メソッドパラメータリストで右辺値参照として定義されているように見えるため、これらのエラーはわかりませんoOther。渡すときに左辺値の非r-refで問題が発生するのはなぜですか同じ変数?)

質問は 2 つあります。1 つは実用的な質問で、もう 1 つは好奇心に関する質問です。

  1. プライマリ:このコードを標準参照から右辺値参照に変更したコーダーは、この状況ではムーブ セマンティクスが最適であると考えて変更したと思われます。割り当てにはポインター値のコピーのみが含まれますが、これはそれほど面倒ではありません。 それらが適切である場合、このコードに右辺値参照を正しく使用するにはどうすればよいですか?

  2. 二次: (好奇心のみ。) 2007 および 2010 のコンパイラは、このコードから何を作成しましたか? 参照への参照として読まれましたか?2 つの&演算子が合体して 1 つの参照になりましたか? おそらく無効な構文であるにもかかわらず、コンパイルして正常に動作したため、一体何をしていたのでしょうか?

4

1 に答える 1

0

問題の解決策として、std::forward を使用できます。

コードを次のように変更するだけです。

#include <utility>   
CopyAndTakeOwnershipFrom(std::forward<VOperandValue>(oOther));

この問題は、移動セマンティクスを 2 つの関数で転送したいが、最初の関数で移動されたオブジェクトに名前が付けられるために発生します。名前があると、std::forward がなければ右辺値ではなくなりますが、左辺値は CopyAndTakeOwnershipFrom の T&& パラメーターに使用できません。C++ Builder 2010 で以前は機能していたのは、XE4 で修正されたバグのようです。

于 2014-04-18T16:58:48.447 に答える