Создание не копируемых, но подвижных объектов в C++
Просто вопрос. Глядя на библиотеки C++ Boost (в частности, класс boost:: thread), я подумал: "Как создать класс, определяющий объекты, которые нельзя скопировать, но которые можно вернуть из функции?"
Хорошо рассмотрим этот пример, класс boost:: thread имеет характеристики, о которых я упоминал ранее, поэтому возможно сделать это:
boost::thread make_thread();
void f()
{
boost::thread some_thread=make_thread();
some_thread.join();
}
Ну, это означает, что объект boost:: thread не может быть скопирован, но возвращен из функции, это возможно. Как это возможно????
Я предполагаю, что конструктор копирования не должен быть предоставлен, но как справиться с возвратом из функции? не нужно ли использовать конструктор копирования???
Спасибо
2 ответа
Это будет возможно в C++1x, который обеспечивает семантику перемещения через ссылки на rvalue. Используя это, вы можете реализовать перемещение и / или копирование отдельно:
class my_class {
private:
data_t* data_;
public:
my_class(const my_class& rhs) // copy constructor
: data_(rhs.data_.clone())
{}
my_class(my_class&& rhs) // move constructor
: data_(rhs.data_)
{
rhs.data_ = NULL;
}
~my_class() {delete data_;} // noop if data_==NULL
my_class& operator=(my_class rhs) // copy assignment
{
this->swap(rhs);
}
my_class& operator=(my_class&& rhs)// move assignment
{
this->swap(rhs);
}
// ...
};
Копирование и перемещение могут быть запрещены отдельно, поэтому вы можете настроить классы, которые можно перемещать, но не копировать.
Конечно, есть несколько волшебных трюков, которые позволяют вам делать это, даже если ваш компилятор еще не поддерживает семантику перемещения (std::auto_ptr
после того, как все перемещается вместо копирования при назначении), так что это может работать для boost::thread
даже при отсутствии семантики перемещения.
Это сложная тема C++, если вы хотите сделать это в C++03. См. Пример эмуляции Говарда Хиннанта Unique_ptr C++03.
Он в основном работает, используя несколько тонких правил в разрешении перегрузки C++, в частности правило, что неконстантные ссылки не могут связываться с временными значениями rvalue, и что неконстантные функции преобразования могут по-прежнему вызываться для неконстантных временных значений.
Вы также можете использовать технику auto_ptr, применяемую в C++03, которая, тем не менее, рассматривается как разбитая несколькими группами, поскольку auto_ptr позволяет копировать переменные, но красть ресурсы из объекта copied-from (другие группы имеют другие мнения по этому поводу).