Constructeur de copie et affectation par défaut pour la classe avec constructeur et affectation de déplacement

Disons que j’ai ce cours:

class Test { public: Test(); }; 

AFAIK, le compilateur fournit le constructeur de copie par défaut et les opérateurs d’assignation, qui affectent chaque membre d’une autre instance à l’instance actuelle. J’ajoute maintenant le constructeur et l’assignation de déplacement

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

Cette classe contient-elle toujours le constructeur de copie généré par le compilateur et les opérateurs d’assignation, ou dois-je les implémenter?

Modifier . Ceci est mon test:

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

Impressions 2 12345 2 12345 . Comstackr: VC ++ 2010. Selon ce test, le constructeur de copie et l’affectation sont toujours là. Est-ce que ce comportement standard, puis-je être sûr que cela fonctionnera sur chaque compilateur C ++?

De 12.8-7 Copier et déplacer des objects de classe [class.copy]

Si la définition de classe ne déclare pas explicitement un constructeur de copie, celui-ci est déclaré implicitement . Si la définition de classe déclare un constructeur de déplacement ou un opérateur d’affectation de déplacement, le constructeur de copie implicitement déclaré est défini comme supprimé. sinon, il est défini par défaut (8.4). Ce dernier cas est déconseillé si la classe a un opérateur d’affectation de copie déclaré par l’utilisateur ou un destructeur déclaré par l’utilisateur …

De 12.8-18

Si la définition de classe ne déclare pas explicitement d’opérateur d’affectation de copie, il en est implicitement déclaré. Si la définition de classe déclare un constructeur de déplacement ou un opérateur d’affectation de déplacement, l’opérateur d’affectation de copie implicitement déclaré est défini comme supprimé. sinon, il est défini par défaut (8.4). Ce dernier cas est déconseillé si la classe a un constructeur de copie déclaré par l’utilisateur ou un destructeur déclaré par l’utilisateur …

Selon cela, puisque vous avez déclaré un constructeur de déplacement et un opérateur d’affectation de déplacement, mais pas d’opérateur d’affectation de copie, de constructeur de copie ou de destructeur, vous n’obtenez pas le constructeur de copie ni l’opérateur d’affectation générés implicitement. Le compilateur vous donne leurs déclarations , mais elles sont déclarées comme deleted .

Voici une version simplifiée de votre exemple:

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

Et l’erreur produite par g ++ 4.8.1

ctors.cpp: 13: 13: erreur: utilisation de la fonction supprimée ‘constexpr Test :: Test (const Test &)’

Test t2 (t1);

ctors.cpp: 1: 8: remarque: ‘constexpr Test :: Test (const Test &)’ est implicitement déclaré comme supprimé, car ‘Test’ déclare un constructeur de déplacement ou un opérateur d’affectation de déplacement

test struct

(c’est moi qui souligne)

Selon la section 12.8 Copier et déplacer des objects de classe de la norme C ++

7 Si la définition de classe ne déclare pas explicitement un constructeur de copie, celui-ci est déclaré implicitement. Si la définition de classe déclare un constructeur de déplacement ou un opérateur d’affectation de déplacement, le constructeur de copie implicitement déclaré est défini comme supprimé. sinon, il est défini par défaut (8.4).

18 Si la définition de classe ne déclare pas explicitement un opérateur d’atsortingbution de copie, il en est déclaré implicitement. Si la définition de classe déclare un constructeur de déplacement ou un opérateur d’affectation de déplacement, l’opérateur d’affectation de copie implicitement déclaré est défini comme supprimé. sinon, il est défini par défaut (8.4).

Ainsi, dans votre cas, le constructeur de copie et l’opérateur d’affectation de copie sont déclarés implicitement par le compilateur, mais définis comme supprimés.