私は、ハンドルを使用するライブラリの周りに小さなラッパーを書いています。このライブラリの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();
}
[MCVE](/ヘルプ/ MCVE)をご提示くださいSomeClass' 'の残りの部分を含んでいます。通常、Handleはデフォルトの移動代入演算子とコンストラクタの生成を妨げてはいけません。 – MikeMB
ゼロの規則(コンパイラ生成のコピー/移動コンストラクタ、コピー/移動代入演算子、デストラクタ)の後にクラスを設計できるかもしれません –
カスタムラッパーを書くのではなく、['std :: unique_ptr'](http ://en.cppreference.com/w/cpp/memory/unique_ptr)を呼び出し、 'destroyHandle()'を呼び出します。 –