11
votes

Interdire l'affectation et passer par la valeur

De ce que je comprends, je suis capable de "désactiver" la copie et l'affectation de mes objets en définissant le constructeur de copie privé et en fonction de l'opérateur d'affectation: xxx

mais quelle est l'utilisation de cela?
Est-il considéré comme une mauvaise pratique?

J'apprécierais si vous pouviez décrire la situation, dans laquelle il serait raisonnable / utile de "désactiver" l'affectation et le constructeur de copie de cette manière.


1 commentaires

Un singleton serait un exemple.


5 Réponses :


0
votes

Lorsque vous essayez de mettre en œuvre un motif singleton, il est parfaitement acceptable d'utiliser un constructeur privé car il est censé être instancié à l'intérieur de lui-même et de nulle part ailleurs. Une fois invoqué, le constructeur ne peut pas être révoqué. Donc, le constructeur est invoqué uniquement après avoir vérifié si la condition singleton satisfaite.


0 commentaires

11
votes

C'est utile quand il n'a pas de sens que votre objet soit copié. Il n'est certainement pas considéré comme une mauvaise pratique.

Par exemple, si vous avez une classe qui représente une connexion réseau, il n'a pas de sens de copier cet objet. Une autre fois que vous voudrez peut-être qu'une classe soit non gêne, c'est si vous aviez une classe représentant un joueur dans un jeu multijoueur. Ces deux classes représentent des choses qui ne peuvent pas être copiées dans le monde réel, ou qui n'ont pas de sens à copier (une personne, une connexion).

En outre, si vous essayez de mettre en œuvre un singleton, sa procédure standard permet de rendre les objets non-copieux.


2 commentaires

Merci, ça a du sens. Qu'en est-il de l'opérateur d'affectation?


@LiHo En général, si vous désactivez un pour désactiver l'autre. Si vous ne désactivez pas l'opérateur d'affectation, vous pouvez le faire: MyClass A, B; a = b; et si vous ne désactivez pas le constructeur de copie, vous pouvez faire myClass B; MyClass A (b); Donc, si vous ne désactivez pas les deux, vous pouvez vous contourner l'autre d'être désactivé.



2
votes

C'est une pratique assez courante. Il y a beaucoup d'exemples où la copie n'est pas appropriée.

Disons que votre objet représente une prise ouverte côté serveur (c'est-à-dire une connexion réseau entrante); Quelle serait la sémantique de faire une copie de cet objet?


0 commentaires

5
votes

De manière générale, une classe qui gère une ressource devrait être autre que de la sémantique de copie spécialisée. L'inverse est vrai aussi: toute classe qui est non copieuse ou nécessite une sémantique spécialisée de copie est la gestion d'une ressource. "Gérer une ressource" dans le C ++ Lingua dans la pratique signifie responsable de certains espaces en mémoire, ou pour une connexion à un réseau ou à une base de données, ou une poignée à un fichier, ou une transaction d'annulation, etc.

ressource La direction capture beaucoup d'exemples. Ce sont des responsabilités qui prennent une opération de préfixe, une opération suffixe et éventuellement une action entre les deux. La gestion de la mémoire, par exemple, implique d'acquérir une poignée à une adresse mémoire que nous allons gérer, peut-être gâcher avec cette mémoire et libérer enfin la poignée (parce que si vous aimez quelque chose, laissez-le libre). < Pré> xxx

Cette classe La classe est presque correcte: elle acquiert automatiquement l'espace mémoire sous-jacent et le libère automatiquement, même si une exception se propage quelque temps après avoir acquis sa ressource. Mais considérez ce scénario: xxx

parce que nous n'avons pas fourni une sémantique spécialisée de copie pour mémoire , le compilateur fournit son propre constructeur de copie et copier l'affectation. Celles-ci font la chose mauvaise chose: m2 = m1 signifie m2.p = m1.p , tel que les deux pointeurs pointeront à la même adresse. Il est faux parce que lorsque m2 est hors de portée, il libère sa ressource comme un bon objet responsable, et lorsque m1 est hors de portée de la portée qui libère sa ressource, cette même ressource M2 a déjà libéré, complétant un double-Supprimer - un scénario de comportement non défini notoire. De plus, en C ++, il est extrêmement facile de faire des copies d'un objet sans même remarquer: une fonction prenant son paramètre par valeur, renvoyant son paramètre par valeur ou prenant son paramètre par référence, mais appelant une autre fonction qui prend elle-même (ou renvoie) son paramètre par valeur ... Il est plus facile de supposer que les choses vont vont être copiées.

tout cela pour dire que lorsqu'une classe 'raise d'arrière est gérant une ressource Ensuite, vous devriez immédiatement savoir que vous devez gérer la copie. Vous devriez décider

  • Vous soutenez la copie, alors que vous décidez de savoir ce que la copie signifie: partage sûr de la ressource, effectuant une copie profonde de la ressource sous-jacente, donc il n'y a pas de partage que ce soit, ni de combiner les deux approches comme dans copie-write ou copie paresseuse. Quel que soit le chemin que vous choisissez, vous devrez fournir un constructeur de copie spécialisé et un opérateur d'affectation de copie.
  • ou vous ne prenez aucune sorte de copie de la ressource, auquel cas vous désactivez le constructeur de copie et l'opérateur d'affectation de copie.

    J'irais jusqu'ici et disons que la gestion des ressources est le seul cas où vous désactivez la copie ou de fournir une sémantique de copie spécialisée. Ceci est juste une autre perspective sur la règle de trois .


0 commentaires

0
votes

Lorsque vous êtes autorisé à créer une instance d'objet uniquement après avoir vérifié comme dans le cas de Singleton, vous avez besoin de constructeurs privés. Lorsque le constructeur est appelé l'instance d'objet sera appelé, puis il n'ya aucun point de vérifier s'il existe déjà une autre instance. Donc, ce que nous faisons, c'est appeler une fonction de membre de la classe à partir de la fonction principale et à l'intérieur de cette fonction de fonction si une autre instance est déjà dans la mémoire. Si non constructeur est appelé. sinon avorté. Vérifiez les classes Singleton ou d'autres classes protégées où les données de l'objet doivent être sécurisées et ne doivent pas être autorisées à copier.

Vérifiez également ceci: classe Singleton en C ++


0 commentaires