Подтвердить что ты не робот

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

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

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

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

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;
    }
};
4b9b3361

Ответ 1

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

Цитата из блог Andrzej С++

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

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

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

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

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

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

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

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

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

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