J'ai vu default
utilisé à côté des déclarations de fonctions dans une classe. Quel est son rôle ?
class C {
C(const C&) = default;
C(C&&) = default;
C& operator=(const C&) & = default;
C& operator=(C&&) & = default;
virtual ~C() { }
};
J'ai vu default
utilisé à côté des déclarations de fonctions dans une classe. Quel est son rôle ?
class C {
C(const C&) = default;
C(C&&) = default;
C& operator=(const C&) & = default;
C& operator=(C&&) & = default;
virtual ~C() { }
};
C'est un nouvelle fonction C++11 .
Cela signifie que vous voulez utiliser la version générée par le compilateur de cette fonction, et que vous n'avez pas besoin de spécifier un corps.
Vous pouvez également utiliser = delete
pour spécifier que vous Ne le fais pas. voulez que le compilateur génère cette fonction automatiquement.
Avec l'introduction des constructeurs de déplacement et des opérateurs d'affectation de déplacement, les règles permettant de déterminer quand les versions automatiques des constructeurs, des destructeurs et des opérateurs d'affectation sont générées sont devenues assez complexes. En utilisant = default
et = delete
facilite les choses car il n'est pas nécessaire de se souvenir des règles : il suffit de dire ce que l'on veut qu'il se passe.
= delete
est plus forte : cela signifie que l'utilisation de cette fonction est interdite, bien qu'elle participe toujours à la résolution des surcharges.
Mais, si nous voulons utiliser la définition générée par le compilateur, alors ne devrions-nous pas sauter l'écriture de cette fonction au lieu de "l'écrire d'abord et l'assigner ensuite à la valeur par défaut" ?
Il s'agit d'une nouvelle fonctionnalité de C++0x qui indique au compilateur de créer la version par défaut du constructeur ou de l'opérateur d'affectation respectif, c'est-à-dire celui qui effectue simplement l'action de copie ou de déplacement pour chaque membre. C'est utile parce que le constructeur de déplacement n'est pas toujours généré par défaut (par exemple, si vous avez un destructeur personnalisé), contrairement au constructeur de copie (et de même pour l'affectation), mais s'il n'y a rien de non trivial à écrire, il est préférable de laisser le compilateur s'en occuper plutôt que de l'écrire vous-même à chaque fois.
Notez également qu'un constructeur par défaut ne sera pas généré si vous fournissez un constructeur autre que celui par défaut. Si vous voulez toujours le constructeur par défaut, vous pouvez utiliser cette syntaxe pour que le compilateur en crée un.
Autre cas d'utilisation, il existe plusieurs situations dans lesquelles un constructeur de copie ne serait pas généré implicitement (par exemple, si vous fournissez un constructeur de déplacement personnalisé). Si vous voulez toujours la version par défaut, vous pouvez la demander avec cette syntaxe.
Voir la section 12.8 de la norme pour plus de détails.
C'est nouveau dans C++11, voir ici . Cela peut être très utile si vous avez défini un constructeur, mais que vous souhaitez utiliser des valeurs par défaut pour les autres. Avant C++11, vous deviez définir tous les constructeurs une fois que vous en aviez défini un, même s'ils sont équivalents aux valeurs par défaut.
Notez également que, dans certaines situations, il est impossible de fournir un constructeur par défaut défini par l'utilisateur qui se comporte de la même manière que le constructeur synthétisé par le compilateur dans les deux cas. par défaut et valeur l'initialisation. default
vous permet de retrouver ce comportement.
Projet de norme C++17 N4659
https://github.com/cplusplus/draft/blob/master/papers/n4659.pdf 11.4.2 "Fonctions à défaut explicite" :
1 Une définition de fonction de la forme :
attribute-specifier-seq opt decl-specifier-seq opt declarator virt-specifier-seq opt = default ;
est appelée une définition explicitement défectueuse. Une fonction qui est explicitement mise en défaut doit
(1.1) - être une fonction membre spéciale,
(1.2) - ont le même type de fonction déclaré (à l'exception d'éventuels qualificatifs de référence différents et à l'exception du fait que dans le le cas d'un constructeur de copie ou d'un opérateur d'affectation de copie, le type de paramètre peut être "référence à non-const T", où T est le nom de la classe de la fonction membre) comme si elle avait été déclarée implicitement, et
(1.3) - ne pas avoir d'arguments par défaut.
2 Une fonction explicitement définie par défaut qui n'est pas définie comme supprimée peut être déclarée constexpr seulement si elle aurait aurait été implicitement déclarée comme constexpr. Si une fonction est explicitement définie par défaut lors de sa première déclaration, elle est implicitement considérée comme constexpr si la déclaration implicite le serait.
3 Si une fonction qui est explicitement mise en défaut est déclarée avec un spécificateur noexcept qui ne produit pas la même spécification d'exception que la déclaration implicite (18. spécification d'exception que celle de la déclaration implicite (18.4), alors
(3.1) - si la fonction est explicitement mise en défaut lors de sa première déclaration, elle est définie comme supprimée ;
(3.2) - sinon, le programme est mal formé.
4 [ Exemple :
struct S { constexpr S() = default; // ill-formed: implicit S() is not constexpr S(int a = 0) = default; // ill-formed: default argument void operator=(const S&) = default; // ill-formed: non-matching return type ~ S() noexcept(false) = default; // deleted: exception specification does not match private: int i; // OK: private copy constructor S(S&); }; S::S(S&) = default; // OK: defines copy constructor
- fin de l'exemple ]
5 Les fonctions défectueuses explicitement et les fonctions implicitement déclarées sont appelées collectivement fonctions défectueuses, et l'implémentation doit leur fournir des définitions implicites (15.1, 15.4, 15.8), ce qui peut signifier les définir comme supprimées. les définir comme supprimées. Une fonction est fournie par l'utilisateur si elle est déclarée par l'utilisateur et n'est pas explicitement définie par défaut ou supprimée lors de sa première déclaration. Une fonction fournie par l'utilisateur et explicitement définie par défaut (c'est-à-dire, explicitement définie par défaut après sa première déclaration) est définie à l'endroit où elle est explicitement définie par défaut ; si une telle fonction est implicitement définie comme étant supprimée, le programme est mal formé. [Note : Déclarer une fonction comme étant défectueuse après sa première déclaration peut permettre une exécution efficace et une définition concise, tout en permettant de réduire les coûts. peut fournir une exécution efficace et une définition concise tout en permettant une interface binaire stable à une base de code évolutive. base de code. - note de fin ]
6 [ Exemple :
struct trivial { trivial() = default; trivial(const trivial&) = default; trivial(trivial&&) = default; trivial& operator=(const trivial&) = default; trivial& operator=(trivial&&) = default; ~ trivial() = default; }; struct nontrivial1 { nontrivial1(); }; nontrivial1::nontrivial1() = default; // not first declaration
- fin de l'exemple ]
Ensuite, la question est bien sûr de savoir quelles fonctions peuvent être déclarées implicitement et quand cela se produit, ce que j'ai expliqué à la page suivante :
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.
29 votes
Que fait le "&" qui précède le "=" dans les déclarations d'opérateurs d'affectation ?
8 votes
@dshin C'est un la requalification d'une fonction membre .