Почему конструктор перемещения неявно удаляется при определении деструктора - PullRequest
0 голосов
/ 24 апреля 2018

Мне интересно, почему комитет решил, что конструктор перемещения неявно удаляется при определении деструктора.

#include <iostream>
#include <vector>
#include <memory>

struct A { 
  ~A(){}; 
  std::unique_ptr<int> a;
};


int main()
{
    A a;
    A b = std::move(a);
}

http://coliru.stacked -crooked.com / а / c0c067fc51260794

Существует ли какой-либо утопический сценарий использования, для которого имеет смысл это правило "не перемещать членов по умолчанию"?

Ответы [ 2 ]

0 голосов
/ 24 апреля 2018

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

Простой пример:

struct String
{
    char *s = nullptr;
    size_t size = 0;

    String(char const* s); // makes a copy of the string

    ~String()
    {
        delete[] s;
    }
};

Если бы стандарт позволял генерацию неявного конструктора перемещения, что бы он делал?Он просто инициализирует s и size в целевом объекте, но не назначит их nullptr и 0 соответственно в исходном объекте.Это затем приводит к двойному удалению в деструкторе исходного и целевого объекта и неопределенном поведении.

Неявная генерация оператора назначения копирования также приводит к аналогичным проблемам.


Обратите внимание, что C ++11 устарела неявная генерация копии специальных членов, а также для приведенного выше примера.К сожалению, они не могут быть определены как удаленные, потому что это нарушит слишком много кода.

[class.copy.ctor] / 6

Если определение класса явно не объявляет конструктор копирования, неявный объявляется неявно.Если определение класса объявляет конструктор перемещения или оператор присваивания перемещения, неявно объявленный конструктор копирования определяется как удаленный;в противном случае он определяется как дефолтный. Последний случай считается устаревшим, если в классе есть пользовательский оператор назначения копирования или пользовательский деструктор.

0 голосов
/ 24 апреля 2018

Логика такова: если вы определяете деструктор, который подразумевает, что он высвобождает ресурсы, так что сгенерированные компилятором конструкторы и присваивания, вероятно, не подходят.

...