Когда использовать Move Constructors / Assignments

Я искал, но не могу найти ответ на "Когда" использовать их. Я просто продолжаю слышать, что это хорошо, потому что это экономит мне эту дополнительную копию. Я использовал это в каждом классе, который у меня был, но кое-что из этого не имело смысла для некоторых классов: S Я прочитал бесчисленные учебники по LValues и RValues и std :: move против std :: copy vs. memcpy против memmove и т. д. И даже читайте о throw (), но я также не уверен, когда это использовать.

Мой код выглядит так:

struct Point
{
    int X, Y;

    Point();
    Point(int x, int y);
    ~Point();

    //All my other operators here..
};

Затем у меня есть массив классов такого типа (RAII sorta вещь):

class PA
{
    private:
        std::vector<Point> PointsList;

    public:
        PA();
        //Variadic Template constructor here..
        ~PA();
        //Operators here..
 };

Должен ли я использовать конструктор перемещения и копирования конструктор? У меня было это в Классе Пункта, но это было странно, таким образом я удалил это. Потом у меня было это в классе PA, но я думал, что это ничего не сделает, поэтому я тоже удалил это. Затем в моем классе растровых изображений мой компилятор жаловался на наличие членов-указателей, но без перегрузки, поэтому я сделал:

//Copy Con:
BMPS::BMPS(const BMPS& Bmp) : Bytes(((Bmp.width * Bmp.height) != 0) ? new RGB[Bmp.width * Bmp.height] : nullptr), width(Bmp.width), height(Bmp.height), size(Bmp.size), DC(0), Image(0)
{
    std::copy(Bmp.Bytes, Bmp.Bytes + (width * height), Bytes);
    BMInfo = Bmp.BMInfo;
    bFHeader = Bmp.bFHeader;
}

//Move Con:
BMPS::BMPS(BMPS&& Bmp) : Bytes(nullptr), width(Bmp.width), height(Bmp.height), size(Bmp.size), DC(0), Image(0)
{
    Bmp.Swap(*this);
    Bmp.Bytes = nullptr;
}

//Assignment:
BMPS& BMPS::operator = (BMPS Bmp)
{
    Bmp.Swap(*this);
    return *this;
}

//Not sure if I need Copy Assignment?

//Move Assignment:
BMPS& BMPS::operator = (BMPS&& Bmp)
{
    this->Swap(Bmp);
    return *this;
}

//Swap function (Member vs. Non-member?)
void BMPS::Swap(BMPS& Bmp) //throw()
{
    //I was told I should put using std::swap instead here.. for some ADL thing.
    //But I always learned that using is bad in headers.
    std::swap(Bytes, Bmp.Bytes);
    std::swap(BMInfo, Bmp.BMInfo);
    std::swap(width, Bmp.width);
    std::swap(height, Bmp.height);
    std::swap(size, Bmp.size);
    std::swap(bFHeader, Bmp.bFHeader);
}

Это правильно? Я сделал что-то плохое или неправильное? Мне нужно бросить ()? Должны ли мои операторы присваивания и перемещения быть такими же? Нужно ли мне задание на копирование? Ах, так много вопросов: c Последний форум, на котором я спрашивал, не мог ответить на все вопросы, поэтому я остался в замешательстве. Наконец, я должен использовать unique_ptr для байтов? (Который является массивом байтов / пикселей.)

Ответы на вопрос(3)

Решение Вопроса

Блог Скотта Мейера:

First, not all copy requests can be replaced by moves. Only copy requests for rvalues are eligible for the optimization. Second, not all types support move operations that are more efficient than copying operations. An example is a std::array. Third, even types that support efficient move operations may support them only some of the time. Case in point: std::string. It supports moves, but in cases where std::string is implemented using SSO (the small string optimization), small strings are just as expensive to move as to copy!

Возможно, вы можете классифицировать ваши типы соответственно, а затем решить, какие всеneed переместить семантику. Обратите внимание, что существуют ограничения на автогенератор компиляторов / операторы присваивания, поэтому вам следует помнить об этом. Это помогает, когда выexplicitly указание участников движения.

Для классов, в которых вы не указываете явное перемещение членов, есть несколько проблем. Существует также проблема явно / неявноdeleted переместить элемент, который запрещает копирование изrvalues, Весьма ценный источник проблем с неявным созданием движущихся членов можно найти в статье Страуструпа под названиемДвигаться или не двигаться.

Относительно обработки исключений с семантикой перемещения я бы рекомендовал пост Дэйва Абрахама.Исключительно Переезд.

I'll try to come back to this answer with some examples when I get the time. Hopefully, for the time being the above mentioned links will help you get started.

 Brandon19 июн. 2012 г., 03:01
Это определенно заставило меня задуматься. Он не отвечал на некоторые вопросы, на которые мне хотелось бы знать конкретные ответы, но для меня это более чем достаточно, чтобы начать учиться самостоятельно. Большое спасибо.

First and foremost: Используйте & quot;Rule of Zero& Quot; везде, где ты можешь. Смотрите & quot;Правило три / пять / ноль& Quot; и & quot;С-20& Quot ;.

Поэтому: ваш & quot; странный & quot; чувство было правильным:Point а такжеPA не нужны явные операторы копирования / перемещения. В противном случае ответыdirkgently а такжеdirvine и их ссылки хорошо читаются для более глубокого понимания.

Что касаетсяBMPS это, конечно, хорошая идея - предоставить явные операторы перемещения.

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

Как ранее говорил Бьярн Страуструп, мы должны прекратить делиться всем и иметь указатели повсюду. Если вы используете указатели, используйте unique_ptr, а не shared_ptr, если только вы абсолютно не хотите делиться собственностью (что во многих случаях вам не нужно). Конструктор Unique_ptr и его только перемещение (в любом случае, хорошо удаленная копия) является хорошим примером объекта, который должен обеспечивать перемещение и никогда не копировать.

Move - это замечательно, и написание конструкторов move - очень хорошая идея, даже лучше, когда msvc догоняет и позволяет удалять / использовать декораторы по умолчанию для сгенерированных компилятором конструкторов (копировать / назначать и т. Д.). Ошибки, такие как попытка получить доступ к ранее удаленному члену, очень полезны, поскольку простое закрытие некоторых конструкторов имеет менее очевидное намерение для сопровождающего кода. В тех случаях, когда копирование в порядке, но перемещение предпочтительнее, мы надеемся, что компилятор предпочтет переместить его, когда сможет (т.е. протестировать с vector.push_back, который с некоторыми компиляторами переместится, или emplace_back, если это разумно, покупая мгновенный прирост производительности),therefore even in copy constructor objects a defined move constructor may automatically be selected improving performance (хорошо игнорируя все обсуждения SSO, которые бушуют в данный момент).Это достойный ответ для ознакомления

В списке рассылки поддержки есть несколько довольно тяжелых тем о преимуществах / недостатках перемещения / копирования и передачи по значению / ссылке, которые все очень много говорят о похожих проблемах, если вы ищете дополнительную информацию.

 Brandon19 июн. 2012 г., 03:03
Я определенно оценил эту ссылку и объяснение. И тебе спасибо! Ссылка была определенно полезной.

Ваш ответ на вопрос