2016-06-26 3 views
0

Я пишу небольшую обертку вокруг библиотеки, которая использует ручки.C++ move операторов класса

Основные виды использования этой библиотеки являются:

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

Я должен написать явно переместить операторы присваивания конструктор/перемещение:

Здесь вы ошибаетесь. Либо не пишите их вообще, а компилятор, или =default; их.

SomeClass a; 
m_vector.push_back(a); 

Вы сделали это неправильно, это должно быть:

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

«В этом случае someclass не копируется, поэтому компилятор будет иметь ошибку, потому что a.m_handle удалили операторы копирования». Я знаю это, но я согласен, что это было плохо сформулировано. – Aulaulz

 Смежные вопросы

  • Нет связанных вопросов^_^