2016-06-26 63 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; 
} 

这当然不难,但我不知道是否有办法避免这种情况,因为那样会产生大量冗余代码。

如果这是不可能的,为什么移动操作符不是由编译器生成的?让我们以下面几行:

SomeClass a; 
m_vector.push_back(a); 

在这种情况下,SomeClass的是不可拷贝,是因为a.m_handle已复制经营删除编译器将有一个错误。所以这意味着我们必须移动它们。但是,如果我们这样做,难道不是因为我们想要移动每个成员(如果我们不能复制它们)吗?

编辑:我只是尝试了一些东西,它似乎工作,只声明移动运营商使用默认值。这是我想去的路。但“为什么”的问题依然存在。

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

我必须明确地写构造移动/移动赋值操作符:

这就是你不对的地方。要么不写他们,让编译器,或他们。

SomeClass a; 
m_vector.push_back(a); 

你那个做错了,它必须是:

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

“在这种情况下,someclass不可复制,因此编译器将会出现错误,因为a.m_handle已删除复制操作符。”我知道,但我同意这句话措辞不佳。 – Aulaulz