5

私はc ++ 11での移動操作の初心者なので、それで遊んでいます。しかし、私が理解できない何かを見つけました。

#include <iostream>
using namespace std;

class A{
    public:
        A(){cout << "default ctor" << endl;}
        A(const string& str):_str{str}{cout << "parameter ctor" << endl;}
        A(A&& obj):_str{std::move(obj._str)}{cout << "move ctor" << endl;}
        A& operator =(A&& rhs){_str = std::move(rhs._str);cout << "move assignment operation" << endl; return *this;}
        void print(){cout << _str << endl;}
    private:
        string _str;
};

int main(){
    A a("rupesh yadav"); // parameter ctor
    A b(std::move(a));   // move ctor

    cout << "print a: ";
    a.print();           // NOT printing  --> CORRECT!!
    cout << "print b: ";
    b.print();           // printing      --> CORRECT!!

    b = std::move(a);    // i don't know may be silly but still lets do it WHY NOT!!!, could be just mistake??

    cout << "print a: "; 
    a.print();           // printing      --> WRONG!! 
    cout << "print b: "; 
    b.print();           // NOT printing  --> WRONG!!
}

オブジェクトにb = std::move(a)もう一度移動を適用しているため、操作が異なる動作をすることを期待していましたが、左側のオブジェクトbを右側のオブジェクトaにコピーしていますが、この部分はわかりません。

または、プログラミングで何か間違ったことをしました。移動操作で何か間違っている場合は助けてください。

編集:これは未定義の動作であることを知っています。私の疑問は、もう一度行う場合、オブジェクトaからオブジェクトbにコピーすることです。もう一度同じことを行う場合、オブジェクトbをオブジェクトaにコピーしますか?

したがって、フォームを左から右、右から左にコピーしているのはなぜですか?

4

2 に答える 2

6

同じオブジェクトから 2 回移動することはできません。

最初に に移動aした後baは「有効だが特定されていない状態」でした (正確な用語を思い出せません)。その後、再びに移動しようとしaました。今、すべてが解き放たれました。(内部的には、データ ポインターが交換されたばかりだと思います。)b

これをしないでください。したい理由がわかりません。

于 2016-05-09T09:56:30.587 に答える
4

オブジェクトから 2 回移動することを妨げるものは何もありません。標準ライブラリ オブジェクトは、移動時に「有効だが未指定」の状態のままにしておく必要があります。唯一の条件は、「オブジェクトの不変条件が満たされ、オブジェクトに対する操作がその型に対して指定されたとおりに動作する」ことです 17.3.28 . 例として、移動コンストラクターは次のようにstd::string言います。

basic_string(const basic_string& str);

basic_string(basic_string&& str) noexcept;

2効果basic_string:表 [tab:strings.ctr.cpy] に示されているクラスのオブジェクトを構築します。2 番目の形式でstrは、指定されていない値を持つ有効な状態のままになります。

移動コンストラクターには前提条件がなく、そこから再び移動しても不変条件に違反しません。さらに、それは標準で明確に概説されているため、定義上、未定義の動作ではありません。std::stringただし、の不変条件に違反することは未定義の動作であると省略して主張することもできますが、次のようになります。

の呼び出しoperator<<std::string許可されていませんか? からの説明には次のように書かれcppreferenceています。

FormattedOutputFunctionとして動作し ます。sentry オブジェクトを構築してチェックした後、次のように出力形式のパディングを決定します。

  • str.size()が 未満でない場合はos.width()、範囲[str.begin(), str.end())をそのまま使用します

  • それ以外の場合は、文字シーケンスの後に文字のコピーを (os.flags() & ios_base::adjustfield) == ios_base::left配置しますos.width()-str.size()os.fill()

  • それ以外の場合は、文字シーケンスの前に文字os.width()-str.size()のコピーを配置しますos.fill()

size()、前提条件がないためbegin()end()コードは完全に安全です。

于 2016-05-09T10:27:15.057 に答える