2013-06-13 2 views
28

Когда неявные конструкторы перемещения недостаточно хороши?Когда неявные конструкторы перемещения недостаточно хороши?

Должен ли я рассматривать его как деструкторы и конструкторы копирования, где это вообще необходимо только, если я управляю своей собственной памятью?

ли неявный шаг конструктора достаточно в этом (очень надуманный) сценарий хорошо:

class A 
{ 
private: 
    B b; 
    std::string name; 

public: 
    A(); 
    std::string getName() const { 
     return name; 
    } 

    B getB() const { 
     return b; 
    } 
}; 

class B 
{ 
private: 
    std::vector list; 

public: 
    B(); 
    std::vector getList() const { 
     return list; 
    } 
}; 
+1

Иногда вам нужно вручную написать конструктор перемещения, чтобы члены «выровнялись» друг с другом. Если у вас есть член строки и член 'int', который ссылается на определенную часть строки, тогда, когда объект перемещается, член' int', вероятно, должен быть сброшен на '0'. –

+2

Неявный конструктор перемещения объекта типа 'A' ​​будет вызывать конструктор перемещения' name' и 'b' (который тоже неявный и вызывает конструктор перемещения' list'). Все движется правильно, вам нечего делать. Напишите свой собственный, если 'A' имеет собственное управление кучей или неперемещаемые члены (в этом случае вы, вероятно, захотите обработать эти элементы-участники отдельно). – Pixelchemist

+1

* «Когда неявные конструкторы перемещения недостаточно хороши?» * - Когда они даже не генерируются глупостью главного поставщика компилятора. ;) (Извините за напыщенность, но определенно самая отвратительно отсутствует в * VC++ *.) –

ответ

24

Ответ здесь основан на результатах поиска Google.

Цитируя Andrzej's C++ blog

> Когда я должен определить конструктор перемещения для моего класса?

Это очень зависит от того, что делает ваш класс и как он реализован. Во-первых, для «агрегатных» классов, которые только группируют другие данные для удобства/ясности, конструкторы перемещения будут неявно генерироваться компилятором. Рассмотрим следующий класс.

struct Country { 
    std::string name; 
    std::vector<std::string> cities; 
}; 

В типичном C++ STRUCT многих специальных функций-членов - как конструктор копирования, копирования присваивания, деструктор - автоматически создаются. Это также включает конструктор перемещения (и назначение перемещения).

Для более сложных классов, которые инкапсулируют детали их реализации, ответ более интересен. Одной из главных целей хода семантики (шаг конструктора, назначение шага), чтобы дать компилятору два инструмента для реализации семантику значений (передачи аргументов по значению, возвратившись по значению) для определенного пользователя типов:

  1. Создания двух одинаковых объекты из одного - это должно быть дорого.
  2. Перемещение одного объекта из одного места памяти в другое - это может быть сделано очень быстро.

Если для вашего класса можно реализовать перемещение конструктора, который будет быстрее, чем конструктор копирования, вы должны реализовать его во время выполнения целей оптимизации скорости. Мы видели, как он может быть реализован для вектора в this link. Однако не для всех типов может быть реализован такой конструктор перемещения, который быстрее, чем конструктор копирования. Рассмотрим следующее матричное представление.

class Matrix { 
    std::complex<long double> data[1000][1000]; 
}; 

Поскольку все памяти, необходимые для матричного представления объявляется в области видимости класса (в отличие от вектора, который использует память кучи распределённого) не существует никакого способа, чтобы применить только небольшое количество заданий. Нам нужно будет выполнить копирование для каждого элемента массива. Нет смысла определять конструктор перемещения, поскольку он будет не быстрее копирования.

Еще одна действительная причина для предоставления вашего конструктора перемещения, если вы хотите включить свой тип, который не копируется (поскольку он является RAII-подобным и представляет ресурс), который все еще передается по значению, где копирование не требуется, и хранящихся в контейнерах STL. Эта уникальная семантика собственности объясняется более подробно в this link.

+0

Спасибо, именно ответ, который я искал. – DormoTheNord

+3

@DormoTheNord Добро пожаловать. Кредит должен быть предоставлен Анджей. Я тоже узнал из вашего вопроса. – taocp

16

Обязательный Rule of Zero ответ: дизайн либо классов, которые управляют один ресурс - и, таким образом, отменяют перемещение/копирование/деструкторов/назначение - или классы, которые агрегируют менеджеров ресурсов и не нуждаются в переопределение.

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