1

このコードを考えてみましょう:

#include <iostream>
#include <string>

using namespace std;


class Movable {
public:
    Movable(const string& name) : m_name(name) { }
    Movable(const Movable& rhs) {
        cout << "Copy constructed from " << rhs.m_name << endl;
    }

    Movable(Movable&& rhs) {
        cout << "Move constructed from " << rhs.m_name << endl;
    }

    Movable& operator = (const Movable& rhs) {
        cout << "Copy assigned from " << rhs.m_name << endl;
    }

    Movable& operator = (Movable&& rhs) {
        cout << "Move assigned from " << rhs.m_name << endl;
    }

private:
    string m_name;
};


int main() {
    Movable obj1("obj1");
    Movable obj2(std::move(obj1));
    obj2 = std::move(obj1);     // For demostration only

    const Movable cObj("cObj");
    Movable tObj(std::move(cObj));
    tObj = std::move(cObj);     // For demonstration only
}

その出力は次のとおりです。

Move constructed from obj1
Move assigned from obj1
Copy constructed from cObj
Copy assigned from cObj

ご覧のとおり、これらの行では、

Movable tObj(std::move(cObj));
tObj = std::move(cObj);     // For demonstration only

cObjに移動するつもりですtObj(代入演算子を使用した2番目の移動は、純粋にデモンストレーションを目的としています)。ただし、出力でわかるように、cObjはにのみコピーさtObjます。

上記の例は単なるデモンストレーションであり、これの実際の使用法はわかりません。しかし、私は尋ねます:

  1. constオブジェクトを移動できますか?
  2. できれば安全ですか?

追加:私は尋ねるのを忘れました。constオブジェクトを移動できる場合、どのようにすればよいですか?(const_cast?)

4

2 に答える 2

2

確かに、mutableから移動した結果としてオブジェクトの非状態が変化しない限り。

おそらく、ファイルの内容またはデータベースレコードに対応するオブジェクトがあります。mutableまた、アクセス時にそのデータをメンバーにキャッシュします。これで、実際にオブジェクトを変更せずに、キャッシュされたデータを盗むことでそのオブジェクトを移動できます。したがって、そのオブジェクトがムーブコンストラクターとムーブ代入演算子を持つことは理にかなっています(オブジェクトが移動可能であることは理にかなっています)const Record&&

これは完全に合法であり、C++11標準のセクション12.8p3は次のように規定しています。

クラスの非テンプレートコンストラクターは、最初のパラメーターがタイプ、、、、または、であり、他のパラメーターがないか、他のすべてのパラメーターにデフォルトの引数があるX場合、移動コンストラクターです。X&&const X&&volatile X&&const volatile X&&

およびp19:

ユーザーが宣言したムーブ代入演算子は、タイプ、、、、またはの1つのパラメーターを持つX::operator=クラスの非静的非テンプレートメンバー関数です。XX&&const X&&volatile X&&const volatile X&&

constこのようにして、オブジェクトを移動できます。reopen新しいコピーは、instance-created-via-moveを使用して、古いオブジェクトをそのままにして、他の何かのためにバッファスペースを再利用し、新しい割り当てを回避します。必要に応じて、コンテンツを返す準備ができています(ディスクまたはデータベースを再度ヒットすることにより)。

于 2013-02-12T04:12:39.750 に答える
2

あなたのコードでは、move-constructorはnon-const引数(Movable&&)を必要とし、引数はconstオブジェクト(std::move(cObj)const Movable&&)であるため、copyコンストラクターが呼び出されます。non-constrvalue-referenceはconstrvalueをバインドできないため、そのオーバーロードは破棄され、次に最適なのはコピーコンストラクターです。

次の質問は、constオブジェクトから移動できるかどうか、いつ移動できるかです。技術的には、をとる移動コンストラクターを実装できますが、const &&未定義の動作を呼び出さずにそれを実行することもできます(ソースオブジェクトの変更不可能なメンバーを変更しないでください)。問題は、それが理にかなっているかどうかです。そして、私はそうは思わない。

移動コンストラクターの存在は、通常、ソースオブジェクトが不要になったときに(たとえば、一時オブジェクトからオブジェクトを構築するときに)別のオブジェクトに効率的に転送できる、オブジェクトによって維持されるリソースがあることを示します。 。移動とは、本質的にソースオブジェクトを変更することです。ソースオブジェクトを変更しない移動コンストラクターは、リソースをソースオブジェクトから宛先オブジェクトに移動することはできず、ほとんどまたはまったく意味がありません。

于 2013-02-12T04:23:09.220 に答える