7
votes

Les lignes de chaîne de 1 caractères sont-elles déjà optimisées pour simples littéraux de type caractère?

souvent lors de la codage en C ++, je vais mettre fin à COUT des instructions avec une nouvelle ligne ( \ n ). Cependant, mon instinct a toujours été d'exprimer cette nouvelle ligne en tant que littéral à chaîne: "\ n" , même s'il s'agit d'un seul caractère et peut être exprimé plus efficacement comme un charcuté ( \ n '). Par exemple: xxx

Il y a un lot du code avec ce phénomène. Donc, la question est la suivante:

  1. existe-t-il toute différence que ce soit dans l'efficacité des deux manières différentes d'exprimer la nouvelle ligne constante? Je ne suis pas préoccupé par la différence réelle dans l'exécution du programme produit (que je suppose serait triviale); Plutôt cela me bugs que peu d'efficacité, cependant minuscule, pourrait être perdue sans raison.

  2. Si la version littérale à chaîne est moins efficace, le compilateur l'optimise-il à la version de la constante de caractères, car les deux offrent exactement le même comportement?

  3. Je suis aussi familier avec std :: endl . La documentation indique que "ce manipulateur est souvent utilisé à tort lorsqu'un simple nouveau ligne est souhaité, conduisant à une mauvaise performance tampon." Et pointe vers Cet article Pour plus d'informations. Toutefois, que l'article indique que les "performances médiocres" ne s'appliquent que pour déposer des E / S et que l'utilisation de endl pour écrire à l'écran peut réellement améliorer les performances. Quel est l'accord avec ça?

    J'ai recherché la bibliothèque standard C ++, mais je n'ai pas trouvé les implémentations des surcharges pertinentes de l'opérateur <<< / code>. J'ai trouvé les déclarations dans ostream.tcc : xxx

    mais pas d'indices quant à la façon dont les mécaniciens bouchent dans la mise en oeuvre. < P> C'est plus une question théorique que tout, donc je ne suis pas intéressé à lire "Il n'y a pas de quart de différence praticable entre les deux." Je sais que. Je me demandais simplement s'il y a une différence du tout et comment le compilateur traite avec cela.


4 commentaires

Le seul "One Char String Literal" qui existe est une chaîne vide. N'oubliez jamais le terminateur zéro.


"\ n" est de type const char [2] , comment cela peut-il être optimisé à un seul caractère? En outre, votre question 3 semble non liée et devrait probablement être affichée comme une question distincte.


L'OP est pleinement conscient de la différence de stockage, les gars. qui est couvert dans le premier paragraphe. L'OP demande si la chaîne C peut être substituée par le compilateur de ce cas spécial d'un caractère. Le seul Char ne nécessite aucun terminateur.


@Praetorian: certainement '\ n' et "\ n" sont différents et ce dernier ne peut pas être optimisé pour l'ancien en général . Mais cout << '\ n' et cout << "\ n" ont exactement le même comportement et un compilateur est autorisé à tirer parti de sa connaissance du Cout et le <<< / code> Opérateur pour transformer l'une à l'autre. Si les compilateurs se préoccupent réellement de le faire est une autre question.


3 Réponses :


1
votes

Je doute fortement, car il change à la fois la mise en page de la mémoire (l'un a un ttérinateur null, l'autre ne signifie pas), et parce que cela impliquerait de modifier le type réel du littéral (et, par extension, changeant la fonction que l'on appelle). Il s'agirait donc d'une transformation invalide dans la grande majorité des cas, et pas assez d'aide dans la minorité minuscule à compter.

qui dit, si le compilateur fait suffisamment d'affranchissement agressif (enlignant la fonction elle-même et les données constantes dans La fonction), vous pourriez vous retrouver avec efficacement le même code. Par exemple, CLANG compile les éléments suivants: xxx

dans ceci: xxx

Comme vous pouvez le constater, l'affranchissement a rendu le deux cas presque identiques. (Et, en fait, le cas '\ n' est légèrement plus complexe car le caractère doit être mis sur la pile.)


2 commentaires

D'autre part, je me souviens de voir printf ("\ n") étant optimisé pour Putc ('\ n') , donc je ne serais donc pas aussi surpris par ce une optimisation.


Printf est un C.EC intégré à optimiser de toutes sortes de façons. Par exemple, printf ("bla \ n") se transforme en met ("bla") .



2
votes

Les différents entre string littéral \ n et endl est-ce:

\ n est un littéral à chaîne qui est annexé à stdout. endl ajoutera également le caractère NEWLINE à STDOUT, cependant, il affleurera également le tampon stdout. Par conséquent, cela peut prendre plus de traitement. Autre que cela, il ne devrait y avoir aucune différence pratique.


0 commentaires

3
votes

Ils sont probablement optimisés pour une chaîne (par unité de compilation) - la plupart des compilateurs "fusionnent des chaînes du même contenu".

J'attendrais qu'il y ait très peu de différence pratique, autre que le fait que vous passez un pointeur à une seule chaîne de caractères.

à vos questions concrètes:

  1. Oui, il y a une légère différence, comme un char * nécessitera une indirection et générera ainsi quelques instructions supplémentaires à exécuter. Pour la sortie de la console (plutôt que la sortie au fichier), il n'est pas important, car le défilement de la console, même en mode texte plein écran, est> 100x Plus d'instructions.
  2. en doute.
  3. SO std :: endl affleurera la mémoire tampon, ce qui réduit effectivement la sortie aux fichiers, car les secteurs ou les blocs partiels sont écrits dans le fichier, ce qui augmente les frais généraux d'appel système. Si vous utilisez "\ n" , le fichier n'est pas rincé tant que le tampon lui-même est rempli, ce qui serait au moins 512 octets, éventuellement autant que plusieurs dizaines de kilo-octets. Mais comme pour la réponse n ° 1, la performance de sortie de la console dépendra davantage de la vitesse que l'écran peut faire défiler l'écran.

0 commentaires