Question

C ++ 11 ajoute la possibilité d'indiquer au compilateur: créer une implémentation par défaut de l’une des fonctions spéciales des membres . Alors que je peux voir la valeur de supprimer une fonction, où est la valeur de explicitement le défaut d'une fonction? Laissez le champ vide et le compilateur le fera quand même.

Le seul point que je peux voir, c'est qu'un constructeur par défaut est créé uniquement lorsqu'il n'existe aucun autre constructeur:

class eg {
public:
    eg(int i);
    eg() = default; 
};

Mais est-ce vraiment mieux que comment vous le faites maintenant?

class eg {
public:
    eg(int i);
    eg() {}
};

Ou me manque-t-il un cas d'utilisation?

Était-ce utile?

La solution

Un constructeur par défaut aura une déclaration et cette déclaration sera soumise aux règles d'accès normales. Par exemple. vous pouvez rendre le constructeur de copie par défaut protégé. Sans ces nouvelles déclarations, les membres générés par défaut sont publics.

Autres conseils

Ces exemples tirés du le site Web de Stroustrup pourraient vous aider à comprendre ce qui suit:

  

Fonctions par défaut et supprimées - Contrôle des valeurs par défaut

     

Le langage courant consistant à "interdire   copie " peut maintenant être exprimé   directement:

class X {
  // ...

  X& operator=(const X&) = delete;    // Disallow copying
  X(const X&) = delete;
};
     

Inversement, on peut aussi dire explicitement   que nous voulons adopter un comportement de copie par défaut:

class Y {
  // ...
  Y& operator=(const Y&) = default;   // default copy semantics
  Y(const Y&) = default;

};
     

Etre explicite sur la valeur par défaut est   évidemment redondant, mais les commentaires à   cet effet et (pire) un utilisateur   définir explicitement les opérations de copie   destiné à donner le comportement par défaut sont   pas rare. Laissant à la   compilateur pour implémenter la valeur par défaut   le comportement est plus simple, moins sujet aux erreurs,   et conduit souvent à un meilleur code objet.   Le " défaut " mécanisme peut être utilisé   pour toute fonction qui a un défaut.   Le " supprimer " mécanisme peut être utilisé pour   toute fonction. Par exemple, nous pouvons   éliminer une conversion indésirable comme   ceci:

struct Z {
  // ...

  Z(long long);     // can initialize with an long long
  Z(long) = delete; // but not anything less
};

En plus de changer l'accessibilité (privée / protégée) des fonctions générées, vous pourrez les rendre virtuelles.

struct S
{
    virtual ~S();
    virtual S& operator=(const S&);
};

S::~S() = default;
S& S::operator=(const S&) = default;

Les aspects suivants des fonctions par défaut peuvent être modifiés:

  • accès (être rendu non public)
  • virtuel
  • explicit (constructeurs)
  • spécifications d'exception
  • const-ness des paramètres

mais pour ce faire, les fonctions doivent être définies en dehors de la classe (8.4.2 / 2 dans Projet de comité final C ++ 0x ).

Une version de la proposition initiale de Lawrence Crowl est ici .

Merci à Roger Pate pour la clarification et la citation.

1) Les destructeurs générés implicitement ne sont actuellement pas virtuels. Il faut donc les définir pour les rendre virtuels, auquel cas ils ne sont pas aussi efficaces. Avec = default, vous aurez des destructeurs virtuels et efficaces en tant que destructeurs générés implicitement.

2) Ils auront des spécificateurs d'accès, contrairement à ceux générés de manière implicite.

3) Si vous insérez votre constructeur par défaut, votre classe reste toujours triviale.

Voici un article développant cette nouvelle fonctionnalité.

Je pense que le fait de pouvoir générer par défaut le constructeur de copie sera réellement utile. Je ne vois pas d'utilisation pour default générant le constructeur par défaut car, comme vous le dites, l'implémentation que vous tapez serait plus courte.

Voir l'article 17 de l'excellent livre de Scott Meyer & Effective Modern C ++ " ;. Il décrit de nombreuses conditions dans lesquelles les constructeurs de copie, les opérations de copie et les opérations de déplacement par défaut sont générés (ou non générés).

En d'autres termes, le compilateur peut ne pas "le faire de toute façon". Mais si la fonction de membre spécial par défaut est logique, l'utilisateur peut utiliser l'option "par défaut". mot clé pour indiquer explicitement au compilateur de générer une fonction par défaut qui, sinon, ne serait pas générée.

Parmi les choses à retenir à la fin du point 17:

  
      
  • Les opérations de déplacement ne sont générées que pour les classes dépourvues d’opérations de déplacement, d’opérations de copie ou de destructeur explicitement déclarées.

  •   
  • Le constructeur de copie est généré uniquement pour les classes dépourvues de constructeur de copie déclaré explicitement. Il est supprimé si une opération de déplacement est déclarée. L’opérateur d’affectation de copie n’est généré que pour les classes dépourvues d’opérateur d’affectation de copie explicitement déclaré. Il est supprimé si une opération de déplacement est déclarée. La génération des opérations de copie dans les classes avec un destructeur explicitement déclaré est déconseillée.

  •   

Pour moi, c’est la fonctionnalité de désactivation qui sera utile. Pour la plupart des classes que je crée actuellement, je désactive la copie et l’amplification; assignation - ce sera bien d’avoir une fonctionnalité que le compilateur peut reconnaître pour le faire, plutôt que de dépendre des erreurs de l'éditeur de liens.

La valeur par défaut est plus utile pour les constructeurs de copie si vous avez une classe avec beaucoup d'attributs. Par exemple, si vous avez cette classe:

class MyClass {
private:
   int offset;
   std::string name;
   std::vector<Person*> relatives;
   float weight;
   MyClass* spouse;
   Vehicle* car;
   double houseArea;
   Date birth;
   Person* parents[2];

public:
   /* Default constructor will be defined here */
};

au lieu de définir le constructeur de copie de cette façon:

MyClass(const MyClass& that) :
   offset(that.offset),
   name(that.name),
   relatives(that.relatives),
   weight(that.weight),
   spouse(that.spouse),
   car(that.car),
   houseArea(that.houseArea),
   birth(that.birth),
   parents(that.parents)
{}

vous définiriez ainsi:

MyClass(const MyClass&) = default;
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top