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

Ошибка компилятора С++ C2280 "попытка ссылки на удаленную функцию" в Visual Studio 2013 и 2015

Этот фрагмент скомпилирован без ошибок в Visual Studio 2013 (версия 12.0.31101.00 Update 4)

class A
{
public:
   A(){}
   A(A &&){}
};

int main(int, char*)
{
   A a;
   new A(a);
   return 0;
}

пока он скомпилирован с этой ошибкой в ​​Visual Studio 2015 RC (версия 14.0.22823.1 D14REL):

1>------ Build started: Project: foo, Configuration: Debug Win32 ------
1>  foo.cpp
1>c:\dev\foo\foo.cpp(11): error C2280: 'A::A(const A &)': attempting to reference a deleted function
1>  c:\dev\foo\foo.cpp(6): note: compiler has generated 'A::A' here
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

Я думаю, что компилятор, поставляемый с Visual Studio 2015, генерирует Copy Constructor и отмечает его как =delete, и поэтому я получаю ошибку C2280 (которая, кстати, я не могу найти документально на msdn.microsoft.com).

Теперь скажем, что у меня есть кодовая база, которая компилируется с Visual Studio 2013 (и она работает, потому что она опирается на код, сгенерированный автоматически компилятором), но не компилируемая с Visual Studio 2015 из-за C2280, как я могу исправить проблема?

Я думал объявить класс A следующим образом:

class A
{
public:
   A(){}
   A(A &&){}
   A(const A&)=default;
};

Мне что-то не хватает?

4b9b3361

Ответ 1

Из [class.copy]/7, мой удар:

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

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

class A
{
public:
   // explicit
   A(){}
   A(A &&){}

   // implicit
   A(const A&) = delete;
   A& operator=(const A&) = delete;
};

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

    A(const A&) = default;
    A& operator=(const A&) = default;

Вам также необходимо объявить оператор присваивания переадресации. Если вам действительно нужны эти специальные функции, вам также, вероятно, понадобится деструктор. См. Правило пяти.

Ответ 2

У меня была та же проблема, и это было связано с плохо определенной переменной-членом:

double const deltaBase = .001;

Ввод этого параметра приведет к удалению конструктора копии. Избавьтесь от "const" и присвойте в конструкторе.

Ответ 3

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

Если вы хотите определить свой собственный конструктор перемещения и использовать конструктор копии по умолчанию, вам нужно объявить его как default, как вы сказали в своем вопросе:

class A
{
public:
   A(){}
   A(A &&){}
   //I know what I'm doing, compiler, use the default version.
   A(const A&)=default;
};

Обратите внимание, что если вы определяете собственный конструктор перемещения, вы должны также подумать о своих операторах присваивания и деструкторе.

Ответ 4

Я застрял с этой ошибкой даже после "по умолчанию" копирования ctor. Оказалось, что один из моих учеников (объект Документа quickjson) запрещал копирование. Изменил его на ссылку, инициализированную с помощью * (new rapidjson :: Document()) в списке инициализатора ctor по умолчанию. Похоже, что все отдельные элементы также должны быть копируемыми в дополнение к ctor по умолчанию.