Comment est-ce que C/C++ copie des structs?
Lors du passage d'une struct en C/C++ en valeur la structure du contenu doit être copié. Comment faire des compilateurs? I. e., qui les instructions de montage sont généralement émises pour cette copie?
À quelle vitesse ces choses, lorsque, par exemple, par rapport à un appel à memcpy?
Maintenant, considérons ce code:
struct X { int i, j, k; };
void foo(X x);
void foo( int i, int j, int k);
Quelle est la différence entre un appel foo(X) et toto(int,int,int), ou le code assembleur généré être la même (en considérant le passage de paramètres)?
Pourquoi ne pas vous le profil et trouver?
Tous les compilateurs options de support pour générer les fichiers d'assemblage à la place de fichiers de l'objet. L'utiliser et de regarder le montage vous-même. Aussi, si le compilateur ne fait une copie ou ne peuvent compter sur des optimisations.
Grigore: Parce que mon profilage résultats pourraient n'être vrai pour mon ordinateur ou mon compilateur. Je suppose que quelqu'un avec une connaissance plus profonde est une meilleure source ici que mon profilage.
Pileborg: là encore, ce n'est vrai que pour mon compilateur et mon code. Il pourrait être possible qu'avec un autre compilateur totalement différentes de ce code est généré. Donc, je veux savoir ce de quelqu'un qui comprend les détails derrière ce processus, non pas à partir d'un test qui essaie juste, sans savoir POURQUOI, ces instructions sont générés.
Si vous voulez une réponse générale qui est valable pour toutes les plateformes et tous les compilateurs, vous ne recevrez pas. La seule chose que vous pouvez faire est de vérifier comment cela fonctionne pour vous, pour votre programme, de votre plate-forme à l'aide de votre compilateur.
Tous les compilateurs options de support pour générer les fichiers d'assemblage à la place de fichiers de l'objet. L'utiliser et de regarder le montage vous-même. Aussi, si le compilateur ne fait une copie ou ne peuvent compter sur des optimisations.
Grigore: Parce que mon profilage résultats pourraient n'être vrai pour mon ordinateur ou mon compilateur. Je suppose que quelqu'un avec une connaissance plus profonde est une meilleure source ici que mon profilage.
Pileborg: là encore, ce n'est vrai que pour mon compilateur et mon code. Il pourrait être possible qu'avec un autre compilateur totalement différentes de ce code est généré. Donc, je veux savoir ce de quelqu'un qui comprend les détails derrière ce processus, non pas à partir d'un test qui essaie juste, sans savoir POURQUOI, ces instructions sont générés.
Si vous voulez une réponse générale qui est valable pour toutes les plateformes et tous les compilateurs, vous ne recevrez pas. La seule chose que vous pouvez faire est de vérifier comment cela fonctionne pour vous, pour votre programme, de votre plate-forme à l'aide de votre compilateur.
OriginalL'auteur gexicide | 2013-02-15
Vous devez vous connecter pour publier un commentaire.
Évidemment, si il y a un constructeur pour la
struct
ouclass
, alors que le constructeur est appelé.Si il n'y a pas un constructeur, il est tout à fait le compilateur, mais plus probablement, pour les trois entier des objets de la taille, il sera probablement de trois
mov
instructions. Pour les plus grandes structures, c'est soit un appel àmemcpy
ou un inline version semblable àmemcpy
.Il est également très probable que, si la structure est TRÈS importante (plusieurs mégaoctets), que la vraie
memcpy
est plus rapide que la version inline, et le compilateur ne peut pas s'en rendent compte et utiliser le inline version, de toute façon. Mais la plupart d'entre nous ne pas utiliser des mégaoctets de grandes structures, donc je ne pense pas en général c'est quelque chose de trop à vous inquiéter. La copie des structs sur la pile des arguments, si la structure est en mégaoctets grande, n'est probablement pas une bonne idée, en premier lieu, compte tenu de la taille restreinte d'un type de pile.OriginalL'auteur Mats Petersson
En C++
Qu'ils appellent le constructeur de copie pour la classe/structure. Le générées implicitement un si vous n'avez pas fournir l'un ou l'une de vous fournir.
Dépend de la classe et de ses membres. Profilage devrait vous donner une image plus claire.
Cependant, l'utilisation de
memcpy
pour copier des instances de classe doit être évitée.En C
Ils effectuent une la copie superficielle pour cette structure. À toutes fins pratiques, vous pouvez le considérer même comme
memcpy
.Mis à jour. Hth.
Je sais qu'ils effectuer une copie superficielle. Mais comment est-ce que celui mis en œuvre.
Vérifiez le code assembleur généré.
Cependant, le compilateur voit ajustement dans le cas particulier. Si, par exemple, pour un tas de
int
s il serait assez stupide pour utiliser un généralmemcpy
, et vous peut (généralement) supposons que votre compilateur de ne pas être stupide.OriginalL'auteur Alok Save
Il y a deux distint cas.
Si votre structure est POD, la copie est optimisé et sera aussi rapide que memcpy (avec le bon niveau d'optimisation).
Si votre structure est pas POD, C++ doit appeler le constructeur de copie pour votre objet. Le constructeur de copie peut appeler d'autres fonctions, de nouveaux opérateurs, etc. ainsi, il sera plus lent que memcpy. Mais
memcpy
de ne pas copier la structure correcty, à l'aide dememcpy
sur un non-POD type de résultats dans un comportement indéterminé!Remarque que, par exemple, dans
g++
l'appel àmemcpy
seront intégrées et optimisées. Que l'intention entre une structure exemplaire et un memcpy appel est exactement le même (copie de X octets à partir de l'emplacement de Y à Z), je ne pense pas que le code assembleur généré diffèrent.De toute façon, pour être sûr, le retrouver par l'analyse de l'assemblage de votre code.
Edit: viens de lire la fin de la question à propos des paramètres de la fonction. Veuillez noter que les paramètres de la fonction de passage est généralement (en particulier en x64) fait dans les registres et il est beaucoup plus rapide que
memcpy
.J'ai vérifié le code assembleur et ils ne diffèrent. Le code exact dépendra de la convention d'appel votre compilateur utilise. Pour moi, la structure n'est pas passé dans les registres, mais c'est plutôt passés sur la pile et une copie est faite. Les trois
int
s sont transmis dans%ecx
,%edx
et%r8d
. J'ai essayé sur Windows de GCC. Il semble qu'il utilise le Windows x64 appel convetion.Pour plus d'informations sur la façon dont les paramètres sont passés à regarder les spécifications de votre convention d'appel. Tous les détails et coin affaires. E. g. pour x64 GCC regarder Système V AMD64 ABI Chapitre 3.2.3 passage de paramètres. Pour Visual Studio look ici.
Le compilateur ne peut pas vraiment optimiser ici. Il est écrit dans la pierre (dans l'appel de la convention, cahier des charges) comment faire pour appeler une fonction, de sorte que le compilateur juste conforme à la spécification. Cela permet à deux fonctions dans les différentes unités de traduction à être reliés ensemble. (Je parle de la non-fonctions inline, bien sûr.)
Est-il également écrit dans la pierre que les services de renseignements doivent être transmis dans les registres? Que faire si je ne dispose pas que de nombreux registres?
C'est une grosse pierre avec de nombreuses règles 🙂 Google "System V AMD64 ABI" et regardez pour le chapitre 3.2.3 passage de paramètres. Je pense que le lien officiel est en baisse, mais il y a beaucoup de miroirs.
OriginalL'auteur Csq
Voir une autre réponse par Alok Enregistrer pour c++. Dans c, il peut être
memcpy
(ou l'équivalent) ou un inline version de celui-ci (jusqu'à unmov
instuction pour les structures avec une bonne taille).OriginalL'auteur Anton Kovalenko