Конструктор копирования по умолчанию и назначение для класса с конструктором перемещения и назначением

Допустим, у меня есть этот класс:

class Test
{
public:
    Test();
};

AFAIK, компилятор предоставляет конструктор копирования по умолчанию и операторы присваивания, которые присваивают каждому члену другого экземпляра текущий экземпляр. Теперь я добавляю конструктор перемещения и присваивание:

class Test
{
public:
    Test();
    Test(Test&& other);
    Test& operator=(Test&& other);
};

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

Редактировать Это мой тест:

class Test
{
public:
    Test(){}

    Test(Test&& other){}
    Test& operator=(Test&& other)
    {
        return *this;
    }

    int n;
    char str[STR_SIZE];
};

int main()
{
    Test t1;
    t1.n = 2;
    strcpy(t1.str, "12345");

    Test t2(t1);

    Test t3;
    t3 = t1;

    cout << t2.n << " " << t2.str << " " << t3.n << " " << t3.str << endl;

    return 0;
}

Печать 2 12345 2 12345, Компилятор: VC++ 2010. Согласно этому тесту, конструктор копирования и назначение все еще здесь. Это стандартное поведение, могу ли я быть уверен, что это будет работать на каждом компиляторе C++?

2 ответа

Решение

От 12.8-7 Копирование и перемещение объектов класса [class.copy]

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

С 12.8-18

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

В соответствии с этим, поскольку вы объявили конструктор перемещения и оператор присваивания перемещения, но не указали оператор копирования, конструктор копирования или деструктор, вы не получите неявно сгенерированный конструктор копирования или оператор присваивания. Компилятор дает вам свои объявления, но они объявлены как deleted,

Вот упрощенная версия вашего примера:

struct Test
{
public:
    Test(){}
    Test(Test&& other){}
    Test& operator=(Test&& other) { return *this;}
};

int main()
{
  Test t1;
  Test t2(t1);
}

И ошибка, вызванная g ++ 4.8.1

ctors.cpp: 13: 13: ошибка: использование удаленной функции 'constexpr Test::Test(const Test&)'

Испытание t2 (t1);

ctors.cpp: 1: 8: примечание: 'constexpr Test::Test(const Test&)' неявно объявлен как удаленный, потому что 'Test' объявляет конструктор перемещения или оператор присваивания перемещения

Тест структуры

(акцент мой)

Согласно разделу 12.8 Копирование и перемещение объектов класса Стандарта C++

7 Если определение класса не объявляет явно конструктор копирования, он объявляется неявно. Если определение класса объявляет конструктор перемещения или оператор присваивания перемещения, неявно объявленный конструктор копирования определяется как удаленный; в противном случае он определяется как дефолтный (8.4).

18 Если определение класса явно не объявляет оператор присваивания копии, он объявляется неявно. Если определение класса объявляет конструктор перемещения или оператор присваивания перемещения, неявно объявленный оператор присваивания копии определяется как удаленный; в противном случае он определяется как дефолтный (8.4).

Таким образом, в вашем случае конструктор копирования и оператор присваивания копии неявно объявляются компилятором, но определяются как удаленные.

Другие вопросы по тегам