2016-03-23 9 views
1

すべてが問題です。私が試した:const/referenceメンバで唯一の移動可能なクラスを作成することはできますか?

#include <vector> 

class Foo 
{ 
    int & _x; 

    public: 
     Foo(int x) : 
      _x(x) 
     {} 

     Foo(Foo && other) : 
      _x(other._x) 
     {} 
     Foo & operator=(Foo && other) = default; 

    private: 
     Foo(Foo const &) = delete; 
     Foo & operator=(Foo const &) = delete; 
}; 

int main(void) 
{ 
    int a, b; 
    std::vector<Foo> vec; 

    vec.push_back(Foo(a)); 
    vec.push_back(Foo(b)); 
    vec.erase(vec.begin()); 
    return 0; 
} 

しかしFoo & operator=(Foo && other)はデフォルトで削除されているので、それはコンパイルできません。

私はこの演算子を削除しようとしましたが、コンストラクタをmoveで使用してコンパイラを強制的に強制しようとしましたが、コピーコンストラクタを使用しようとしました。

参照メンバでオブジェクトを移動することはできますか?

そうでない場合、なぜですか?

ありがとうございました。

編集:私はすでにMove-assignment and reference memberを読んでいますが、私の質問には答えません。なぜFoo & operator=(Foo const &)がコンパイラで使用されているのでしょうか?Foo(Foo && other)は動作します。

なぜ、参照メンバでクラスを移動できないのか分かりません。

+1

参照メンバーを持つクラスは、コピーを作成して構築することはできますが、コピーの割り当てや割り当ての移動はできません。問題は移動ではなく、問題はassign(operator =) –

+0

です。なぜstd :: vectorは演算子=を使用し、移動コンストラクタは使用しませんか?彼らは同じ行動をしていませんか? – Boiethios

+1

いいえ1つのコンストラクトと他のアサイン。 vectorは 'push_back'にコンストラクタを使いますが、' erase'は代入が必要です。 –

答えて

3

eraseは、要素タイプがMoveAssignableであることが必要です。これは単にためeraseは、典型的に実装されている方法である:これは、異なる方法で実装することができる

for (; j != end; ++i, ++j) 
    *i = std::move(*j); 
for (; i != end; ++i) 
    i->~T(); 

、移動構造を使用して:それは、移動-割り当て消去スロットに消去された要素の後にベクターを歩く(または要素)が、それは例外セーフ取得する移動代入演算子は(ほとんどの時間である)存在する場合、非効率的では困難であろう:

for (; j != end; ++i, ++j) 
{ 
    i->~T(); 
    new (&*i) T(std::move(*j)); // what if this throws? 
} 
for (; i != end; ++i) 
    i->~T(); 

あなたはeraseの効果を得るために、別の戦略を使用することによってこの問題を回避でき例えば、

vec = std::vector<Foo>(
    std::make_move_iterator(std::next(vec.begin())), 
    std::make_move_iterator(vec.end())); 

Fooは、参照メンバーを持つ型を移動可能(Move-assignment and reference member)にできないため、それほど有用ではありません。代わりにreference_wrapperを使用できるかどうかを検討する必要があります。

+0

私は参照をパブリックにする(または 'type * const'を使用する)ようにしました。誰もがそれを使用してアドレス値を変更することはできませんでした。しかし、 'get()'を使う必要があるので、reference_wrapperは動作しません。 – Boiethios

関連する問題