2016-06-26 66 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