2016-06-26 21 views
0

私は、ハンドルを使用するライブラリの周りに小さなラッパーを書いています。このライブラリのC++移動演算子クラスメンバ

基本的な用途は以下のとおりです。

int handle; 
createHandle(1, &handle) 
doSomethingWithHandle(handle); 
// ... 
destroyHandle(handle); 

私はRAIIの原則、次のラッパークラスを作った:

Handle::Handle() 
{ 
    createHandle(1, &m_handle); 
} 

Handle::~Handle() 
{ 
    if(m_handle!= 0) 
     destroyHandle(m_handle); 
} 

Handle::Handle(Handle&& h) : 
    m_handle(h.m_handle) 
{ 
    h.m_handle = 0; 
} 

Handle& Handle::operator=(Handle&& h) 
{ 
    m_handle = h.m_handle; 
    h.m_handle = 0; 
    return *this; 
} 

// copy constructor and copy assignment operator are explicitely deleted 

それは働いている、しかし、多くのクラスは、これらのラッパーに依存し、その手段クラスにハンドルメンバーがあるたびに、私は明示的に移動コンストラクタ/移動代入演算子を書く必要があります:

SomeClass::SomeClass(SomeClass&& s) : 
    m_handle(std::move(s.m_handle)) 
{ 

} 

SomeClass& SomeClass::SomeClass(SomeClass&& s) 
{ 
    m_handle = std::move(s.m_handle); 
    return *this; 
} 

これはもちろん難しいことではありませんが、これを避ける方法があるのだろうかと思います。冗長なコードがたくさんあるからです。

これが不可能な場合、なぜ移動演算子はコンパイラによって生成されないのですか?のは、次の行を見てみましょう:a.m_handleは、コピー・オペレータが削除されているので、コンパイラはエラーを持っていますので、この場合は

SomeClass a; 
m_vector.push_back(a); 

は、工assはコピーできません。つまり、私たちはそれらを動かさなければなりません。しかし、もし私たちがそうしていれば、すべてのメンバーを(私たちがそれをコピーすることができない場合)移動させたいと思うのですか?

編集:私は何か試してみましたが、動作するようですが、デフォルトを使用して移動演算子を宣言してください。これは私が推測する方法です。しかし、なぜ "なぜ"の質問が残っています。

EDIT2:もう一つの例

class Test 
{ 
public: 
    Test() 
    { 
     m_vec.resize(10); 
    } 

    Test(const Test&) = delete; 
    Test& operator=(const Test&) = delete; 

    //Test(Test&&) = default; 
    //Test& operator=(Test&&) = default; 

    void cout() 
    { 
     std::cout << m_vec.size() << std::endl; 
    } 

private: 
    std::vector<int> m_vec; 
}; 

int main() 
{ 
    Test a; 

    std::vector<Test> v; 
    v.push_back(std::move(a)); 

    v[ 0 ].cout(); 
} 
+0

[MCVE](/ヘルプ/ MCVE)をご提示くださいSomeClass' 'の残りの部分を含んでいます。通常、Handleはデフォルトの移動代入演算子とコンストラクタの生成を妨げてはいけません。 – MikeMB

+0

ゼロの規則(コンパイラ生成のコピー/移動コンストラクタ、コピー/移動代入演算子、デストラクタ)の後にクラスを設計できるかもしれません –

+0

カスタムラッパーを書くのではなく、['std :: unique_ptr'](http ://en.cppreference.com/w/cpp/memory/unique_ptr)を呼び出し、 'destroyHandle()'を呼び出します。 –

答えて

0

私は明示的にコンストラクタ/移動代入演算子を動かす記述する必要があります:

あなたは間違っている場所です。どちらも書いておらず、コンパイラには=default;を付けてください。

SomeClass a; 
m_vector.push_back(a); 

あなたは間違っている、それがなければならないことをやった:

SomeClass a; 
m_vector.push_back(std::move(a)); 
+0

"この場合、someclassはコピーできないため、a.m_handleにコピー演算子が削除されているため、コンパイラにエラーが発生します。私はそれを知っているが、私はこれがあまり言い表せられていないことに同意する。 – Aulaulz