9
votes

Devrions-nous écrire explicitement un constructeur de copie si le membre de la classe est un vecteur?

struct myType {
    vector<char*> ls;
};
Here ls is holding pointers to char. If a user-defined copy constructor for myType is not provided, will myType's default copy constructor do a deep copy of ls?

1 commentaires

Je veux dire si le vecteur détient n'importe quel pointeur sur un type de données primitif ou défini par l'utilisateur (pointeur sur la classe)


3 Réponses :


8
votes

Le constructeur de copie par défaut sera la copie profonde?

Bien sûr que non. Le compilateur ne peut pas savoir qui possède la mémoire pointue.

Si une copie profonde est requise, vous devez implémenter le constructeur de copie et copier manuellement chaque char * dans la nouvelle mémoire pour le vecteur dans le copié-to Objet .

Si vous utilisez le Char * en tant que chaînes terminées zéro, vous devriez vraiment Utiliser std :: string . Si vous le faites, le constructeur par défaut suffit.


0 commentaires

2
votes

Non, ce ne sera pas.

C ++ appellera récursivement la copie CTOR de tous les sous-objectifs. Donc, il appellera la copie CTOR du vecteur, qui appellera à son tour la copie CTOR du char * qui copiera le char * par valeur. C ++ n'allouera jamais automatiquement de mémoire et copier les données. Il ne peut même pas faire cela, puisqu'il ne sait pas ce que les données sont pointées et combien il devrait copier.

Lorsque vous utilisez des chaînes, vous devez préférer utiliser std :: string , car cela fera tout la copie pour vous. S'il s'agit d'un tampon de données binaires qui nécessite une manipulation spéciale, vous devez le faire vous-même dans votre copie CTOR (et lorsque vous avez terminé, réfléchissez un moment à propos de si c'était vraiment judicieux de penser à la nécessité de le faire pour vous) .

Lorsque vous écrivez votre propre copie CTOR, vous devriez toujours m'occuper du règle de trois


0 commentaires

11
votes

Ici, ls tient le pointeur en caractères. Si le constructeur de copie n'est pas fourni, le constructeur de copie par défaut sera-t-il la copie profonde?

Le constructeur de copie par défaut copiera tous les membres - c.-à-dire appelez leurs constructeurs de copies respectifs. 1 donc oui, un std :: vecteur (étant rien de spécial aussi loin que c ++ est concerné) sera dûment copié.

Cependant, la mémoire pointée par les éléments char * à l'intérieur du vecteur ne sera bien sûr pas, car C ++ ne sait pas et ne se soucie pas de ce que les pointeurs pointaient.

Mais la solution ici n'est pas de fournir un constructeur de copie personnalisé. Il est d'utiliser une structure de données au lieu des pointeurs bruts ( char * ) qui fait. Et cela se trouve être std :: string (ou std :: vecteur en fonction de l'intention).


1 créant ainsi une fermeture transitive de l'opération de copie - c'est la manière dont la copie profonde est généralement mise en œuvre, mais bien sûr, un implémentation de la copie peut toujours séparer de celui-ci.


9 commentaires

"C'est une bonne définition de" Copie profonde "" - si c'est une bonne définition de "Copie profonde", alors quelle "copie peu profonde" ressemblerait-elle? Personnellement, je pense que c'est une "copie". Les termes "Copie profonde" et "Copie peu profonde" sont significatifs si et seulement si l'on considère les éléments du vecteur comme une forme d'indirection. Si cela fait cela, ceci est une "copie peu profonde", mais comme vous dites vecteur ne se soucie pas si ses éléments sont des pointeurs ou autre chose.


@Steve à la lumière du mécanisme de la langue de la construction de la copie, la distinction IMHO n'a aucun sens pour le pointeur / affectation de référence. Mais puisque la CTOR est une manière C ++ 'de définir une opération de copie, et puisque l'appelant un CTOR effectue la fermeture transitive de cette opération de copie sur tous ses membres, il n'a pas de sens d'appeler ce problème mais Copie profonde, Imho. Si vous ne fournissez pas de copie sémantique dans la hiérarchie de fermeture (en utilisant un pointeur brut sans l'associer avec une copie sémantique via encapsulation), vous indiquez explicitement C ++ de renoncer à son mécanisme de copie.


Juste une norme concernant le libellé: les éléments char * dans le vecteur très définitivement sont copiés. Ce qu'ils ne sont pas copiés, c'est ce qu'ils soulignent. (Je suis sûr que c'est ce que vous vouliez dire.)


C'est faux d'appeler la copie en profondeur. Appelez-le strictement ce qu'il est: Copie des membres . Qu'il s'agisse d'une copie profonde ou peu profonde dépend fortement de la structure des données. En disant que ceci est une copie profonde signifierait également la copie d'un pointeur (pas l'objet référé) serait une copie approfondie.


@ EDA-QA Mort-ORA-Y: D'accord, par la définition de Konrad Char * A = 0; Char * b = a; est une copie profonde et il "n'a aucun sens de l'appeler autre chose". En particulier, il n'a pas de sens de l'appeler "une copie", ce qui correspond à ce que la norme l'appelle (affectation de copie dans ce cas). Je ne peux donc pas accepter la terminologie de Konrad et j'espère que personne d'autre ne le fait non plus. J'aime "copier des membres" comme un terme - chaque membre est copié et nous savons tous ce que la copie d'un pointeur signifie. "Copie en profondeur" impliquant un pointeur semble être controversé - je pense que cela signifie copier l'arborescence, Konrad pense que ça ne le fait pas.


@Steve m'a laissé tomber légèrement. Depuis std :: vecteur ne permet pas de spécifier une opération de copie personnalisée pour ses membres et s'appuie sur le mécanisme innate C ++ '(= Copy Construction), il est logique que cela m'aide à appelle cette copie en profondeur, peu importe quoi . En fait, Chaque La mise en œuvre de la copie profonde que je connaisse "offre" un mécanisme à sortir de l'algorithme (semblable à l'affectation du pointeur) si strictement parlant de profond de copier n'existe pas du tout < / i>. Mais peut-être qu'il est plus précis d'appeler CTors un mécanisme de mise en œuvre d'une copie profonde.


Cependant, vos char * éléments à l'intérieur du vecteur ne seront bien sûr pas Oui, ils le feront.


@Llightess je faisais référence aux points de vue (plutôt que les pointeurs). Point valide, je vais clarifier.


Une copie Copie signifie que la copie est identique et distincte . Post Copy, toutes les modifications des objets source ne modifient pas la copie. Si une modification de la source a un effet sur l'objet copié, une copie profonde n'a pas été effectuée.