Je l'ai deviné mais j'étais toujours surpris de voir que la production de ces deux programmes, écrite en C et C ++, lors de la compilation était très différente. Cela me fait penser que le concept d'objets existait toujours au plus bas niveau le plus bas. Est-ce que cela ajoutez des frais généraux? Si oui, est-il actuellement une optimisation impossible de convertir le code orienté objet en style procédural ou tout simplement très difficile à faire?
.file "helloworld.cpp" .text .p2align 4,,15 .type _GLOBAL__I_main, @function _GLOBAL__I_main: .LFB1007: .cfi_startproc .cfi_personality 0x0,__gxx_personality_v0 pushl %ebp .cfi_def_cfa_offset 8 movl %esp, %ebp .cfi_offset 5, -8 .cfi_def_cfa_register 5 subl $24, %esp movl $_ZStL8__ioinit, (%esp) call _ZNSt8ios_base4InitC1Ev movl $__dso_handle, 8(%esp) movl $_ZStL8__ioinit, 4(%esp) movl $_ZNSt8ios_base4InitD1Ev, (%esp) call __cxa_atexit leave ret .cfi_endproc .LFE1007: .size _GLOBAL__I_main, .-_GLOBAL__I_main .section .ctors,"aw",@progbits .align 4 .long _GLOBAL__I_main .section .rodata.str1.1,"aMS",@progbits,1 .LC0: .string "Hello World!" .text .p2align 4,,15 .globl main .type main, @function main: .LFB997: .cfi_startproc .cfi_personality 0x0,__gxx_personality_v0 pushl %ebp .cfi_def_cfa_offset 8 movl %esp, %ebp .cfi_offset 5, -8 .cfi_def_cfa_register 5 andl $-16, %esp pushl %ebx subl $28, %esp movl $12, 8(%esp) movl $.LC0, 4(%esp) movl $_ZSt4cout, (%esp) .cfi_escape 0x10,0x3,0x7,0x55,0x9,0xf0,0x1a,0x9,0xfc,0x22 call _ZSt16__ostream_insertIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_PKS3_i movl _ZSt4cout, %eax movl -12(%eax), %eax movl _ZSt4cout+124(%eax), %ebx testl %ebx, %ebx je .L9 cmpb $0, 28(%ebx) je .L5 movzbl 39(%ebx), %eax .L6: movsbl %al,%eax movl %eax, 4(%esp) movl $_ZSt4cout, (%esp) call _ZNSo3putEc movl %eax, (%esp) call _ZNSo5flushEv addl $28, %esp xorl %eax, %eax popl %ebx movl %ebp, %esp popl %ebp ret .p2align 4,,7 .p2align 3 .L5: movl %ebx, (%esp) call _ZNKSt5ctypeIcE13_M_widen_initEv movl (%ebx), %eax movl $10, 4(%esp) movl %ebx, (%esp) call *24(%eax) jmp .L6 .L9: call _ZSt16__throw_bad_castv .cfi_endproc .LFE997: .size main, .-main .local _ZStL8__ioinit .comm _ZStL8__ioinit,1,1 .weakref _ZL20__gthrw_pthread_oncePiPFvvE,pthread_once .weakref _ZL27__gthrw_pthread_getspecificj,pthread_getspecific .weakref _ZL27__gthrw_pthread_setspecificjPKv,pthread_setspecific .weakref _ZL22__gthrw_pthread_createPmPK14pthread_attr_tPFPvS3_ES3_,pthread_create .weakref _ZL20__gthrw_pthread_joinmPPv,pthread_join .weakref _ZL21__gthrw_pthread_equalmm,pthread_equal .weakref _ZL20__gthrw_pthread_selfv,pthread_self .weakref _ZL22__gthrw_pthread_detachm,pthread_detach .weakref _ZL22__gthrw_pthread_cancelm,pthread_cancel .weakref _ZL19__gthrw_sched_yieldv,sched_yield .weakref _ZL26__gthrw_pthread_mutex_lockP15pthread_mutex_t,pthread_mutex_lock .weakref _ZL29__gthrw_pthread_mutex_trylockP15pthread_mutex_t,pthread_mutex_trylock .weakref _ZL31__gthrw_pthread_mutex_timedlockP15pthread_mutex_tPK8timespec,pthread_mutex_timedlock .weakref _ZL28__gthrw_pthread_mutex_unlockP15pthread_mutex_t,pthread_mutex_unlock .weakref _ZL26__gthrw_pthread_mutex_initP15pthread_mutex_tPK19pthread_mutexattr_t,pthread_mutex_init .weakref _ZL29__gthrw_pthread_mutex_destroyP15pthread_mutex_t,pthread_mutex_destroy .weakref _ZL30__gthrw_pthread_cond_broadcastP14pthread_cond_t,pthread_cond_broadcast .weakref _ZL27__gthrw_pthread_cond_signalP14pthread_cond_t,pthread_cond_signal .weakref _ZL25__gthrw_pthread_cond_waitP14pthread_cond_tP15pthread_mutex_t,pthread_cond_wait .weakref _ZL30__gthrw_pthread_cond_timedwaitP14pthread_cond_tP15pthread_mutex_tPK8timespec,pthread_cond_timedwait .weakref _ZL28__gthrw_pthread_cond_destroyP14pthread_cond_t,pthread_cond_destroy .weakref _ZL26__gthrw_pthread_key_createPjPFvPvE,pthread_key_create .weakref _ZL26__gthrw_pthread_key_deletej,pthread_key_delete .weakref _ZL30__gthrw_pthread_mutexattr_initP19pthread_mutexattr_t,pthread_mutexattr_init .weakref _ZL33__gthrw_pthread_mutexattr_settypeP19pthread_mutexattr_ti,pthread_mutexattr_settype .weakref _ZL33__gthrw_pthread_mutexattr_destroyP19pthread_mutexattr_t,pthread_mutexattr_destroy .ident "GCC: (Ubuntu 4.4.3-4ubuntu5) 4.4.3" .section .note.GNU-stack,"",@progbits
5 Réponses :
Différents compilateurs produisent un code différent. Une première version de GCC par rapport à la version actuelle de GCC produise probablement un code différent. p>
Plus important encore, iostream code> gère beaucoup de choses
stdio code> ne doit donc pas être évidemment des frais généraux substantiels. Je comprends que, en théorie, ceux-ci pourraient être compilés au code indicial, mais ce qu'ils font n'est pas techniquement identique. P>
Votre problème ici ne concerne pas les objets ou l'optimisation: c'est que printf code> et
cout code> sont des bêtes fondamentalement différentes. Pour une comparaison plus équitable, remplacez votre instruction code> code> dans le code C ++ avec
printf code>. L'optimisation est un point de théâtre lorsque vous émettez sur stdout, car le goulot d'étranglement sera certainement le tampon du terminal. P>
+1 Pour avoir repéré la différence, mais s'il vous plaît noter que stdout code> ne signifie pas un terminal, et la surcharge de
COUT code> est souvent négativement sur le débit lorsqu'il est redirigé vers un fichier de disque.
@Tony: true, mais lors de la redirection de / dev / null code>, la fonction à battre n'est pas
printf code>, mais celle qui reconnaît
/ dev / null code> et saute la mise en forme tout à fait.
@Ben VOIGT: Le point ne concerne pas les frais généraux, l'efficacité ou quoi que ce soit. C'est que les programmes originaux sont deux programmes différents qui font des choses différentes, elles ont i> être compilées différemment. Si le même programme a été introduit aux deux compilateurs, le code serait plus similaire.
Vous devez vous rendre compte qu'il y a beaucoup d'autres choses «autres» en C ++. Constructeurs globaux par exemple. Aussi les bibliothèques sont différentes. P>
L'objet de flux C ++ est beaucoup plus compliqué que c io, et si vous regardez via l'assembleur, vous pouvez voir tout le code de Pthreads dans la version C ++. P>
Ce n'est pas nécessairement plus lent, mais c'est certainement différent. P>
Vous n'appelez pas les mêmes fonctions dans l'exemple C ++ comme exemple C. Remplacez les tuyaux STD :: COUT COUT AVEC VIEUX PRINTF UNILE Comme le code C et vous devriez voir une corrélation beaucoup plus grande entre la sortie des deux compilateurs. P>
Je l'ai deviné, mais il était toujours surpris de voir que la production de ces deux programmes, écrite en C et C ++, lors de la compilation était très différente. P>
Je suis surpris que vous ayez été surpris - ce sont des programmes totalement différents. P>
Cela me fait penser que le concept d'objets existe toujours au niveau le plus bas. P> blockQuote>
absolument ... Les objets
sont forts> la mémoire de la manière dont la mémoire est disposée et utilisée lors de l'exécution du programme (sous réserve des optimisations). P> Est-ce que cela ajoutez des frais généraux? P> blockQuote>
Pas nécessairement ou typiquement - les mêmes données devraient être quelque part de toute façon si le travail était coordonné de la même manière logique. P>
Si oui, est-il actuellement une optimisation impossible de convertir le code orienté objet en style de procédure ou tout simplement très difficile à faire? P> BlockQuote>
Le problème n'a rien à voir avec le code de procédure de OO VS, ou d'être plus efficace que l'autre. Le problème principal que vous observez ici est que les ostreams de C ++ nécessitent un peu plus de configuration et de démolition et d'avoir plus d'E / S coordonné par le code en ligne, tandis que PrintF () a plus de lignes dans la bibliothèque précompilie afin que vous Je ne peux pas le voir dans votre petite liste de codes. Ce n'est pas clair vraiment ce qui est "meilleur", et à moins que vous n'ayez un problème de performance que les émissions de profilage sont liées, vous devez l'oublier et obtenir une programmation utile effectuée. P>
Modifier en réponse au commentaire: P >
Appel équitable - était un peu de mots durement - désolé. C'est une distinction difficile à faire en réalité ... "Seul le compilateur [sait] des objets" est vrai dans un sens - ils ne sont pas encapsulés, "choses" discrètes à moitié saintes au compilateur comme ils peuvent être au programmeur . Et, nous pourrions écrire un objet qui pourrait être utilisé exactement comme si vous avez utilisé
cout code> qui disparaîtrait lors de la compilation et de produire du code équivalent à la version Printf (). Mais,
COUT code> et iOSTreams implique une certaine configuration, car il s'agit de fil en sécurité et de plus en plus inlincé et gère différents locaux, et c'est un objet réel avec les exigences de stockage, car il existe des informations plus indépendantes sur l'état d'erreur, que vous souhaitiez des exceptions Des conditions de fin de fichier (Printf () affecte "errno", qui est ensuite classée par le prochain appel de la bibliothèque / système d'exploitation) .... p>
Qu'est-ce que vous pourriez trouver plus perspicace est de comparer comment Beaucoup de code supplémentaire est généré lorsque vous imprimez une chaîne supplémentaire, car la quantité de code est fondamentalement une surcharge constante + une quantité perfontrée de l'utilisation, et de ce dernier considération
ostream code> code-bille peut être aussi efficace. que Printf (), en fonction des types et de la mise en forme demandée. Il convient également de noter que ... p>
xxx pré> ... est correct et plus analogue à votre instruction PrintF () ...
std :: endl code > demande explicitement une opération de rinçage inutile, en tant que programme C ++ conforme à la normalisation, affleurera et fermera ses tampons lorsque le flux est hors de portée de toute façon (cela dit, il y a un poste intéressant aujourd'hui où il semble que le compilateur Microsoft Visualc ++ de quelqu'un ne soit pas le faire pour eux. ! - la peine de garder un œil sur mais difficile à croire). p> blockquote>
Pourquoi avez-vous été surpris? Je ne prétends pas être un expert. L'industrie du logiciel est dur ... J'étais surpris parce que je pensais que dans le capuchon Cout était juste en train de prendre une corde et de la sortir à la console comme si le printf était avec quelques différences, je n'ai pas pensé qu'un objet réel devait être créé. Je pensais que seul le compilateur connaissait des objets.
Ce sont deux programmes différents, la seule chose à laquelle ils ont en commun sont la sortie finale de l'écran. Bien sûr, ils doivent compiler différemment.