Pourquoi string::compare
renvoie un int
au lieu d'un type plus petit comme short
ou char
? Je crois comprendre que cette méthode ne renvoie que -1, 0 ou 1.
Deuxième partie, si je devais concevoir une méthode de comparaison qui compare deux objets de type Foo
et que je ne voulais renvoyer que -1, 0 ou 1, est-ce que l'utilisation short
ou char
généralement serait une bonne idée?
EDIT: J'ai été corrigé, string::compare
ne renvoie pas -1, 0 ou 1, il renvoie en fait une valeur> 0, <0 ou 0. Merci de me garder en ligne les gars.
Il semble que la réponse soit approximativement, il n'y a aucune raison de renvoyer un type plus petit que int
parce que les valeurs de retour sont des "rvalues" et que ces "rvalues" ne bénéficient pas d'être plus petites que le type int (4 octets). En outre, de nombreuses personnes ont souligné que les registres de la plupart des systèmes seront probablement de int
toute façon de toute façon, puisque ces registres vont être remplis que vous leur donniez une valeur de 1, 2 ou 4 octets, il n'y a pas de réel avantage à renvoyer un plus petite valeur.
EDIT 2: En fait, il semble qu'il puisse y avoir une surcharge de traitement supplémentaire lors de l'utilisation de types de données plus petits tels que l'alignement, le masquage, etc. Le consensus général est que les plus petits types de données existent pour économiser la mémoire lorsque vous travaillez avec beaucoup de données, comme dans le cas d'un tableau.
J'ai appris quelque chose aujourd'hui, merci encore les gars!
string::compare()
vous lien vers indique clairement que la valeur de retour est <0, 0 et> 0 -pas- -1, 0 et 1.short
ou à lachar
place deint
? La plupart des architectures vont stocker la valeur de retour d'une fonction dans un registre, et unint
rentrera dans un registre aussi bien qu'unshort
ouchar
. Et utiliserchar
pour les types numériques est toujours une mauvaise idée, en particulier lorsque vous devez garantir que les valeurs signées sont gérées correctement.char
serait une mauvaise idée, car la vérification du code pour la valeur de retour si elle est inférieure à zéro échouera sur les plates-formes oùchar
n'est pas signé.Réponses:
Premièrement, la spécification est qu'elle renverra une valeur inférieure, égale ou supérieure à
0
, pas nécessairement-1
ou1
. Deuxièmement, les valeurs de retour sont des rvalues, soumises à une promotion intégrale, il est donc inutile de renvoyer quelque chose de plus petit.En C ++ (comme en C), chaque expression est une rvalue ou une lvalue. Historiquement, les termes font référence au fait que les valeurs l apparaissent à gauche d'une affectation, alors que les valeurs r ne peuvent apparaître qu'à droite. Aujourd'hui, une simple approximation pour les types non-classe est qu'une lvalue a une adresse en mémoire, pas une rvalue. Ainsi, vous ne pouvez pas prendre l'adresse d'une rvalue, et les qualificatifs cv (qui condition "accès") ne s'appliquent pas. En termes C ++, une rvalue qui n'a pas de type de classe est une valeur pure, pas un objet. La valeur de retour d'une fonction est une rvalue, sauf si elle a un type de référence. (Les types non-classe qui tiennent dans un registre seront presque toujours retournés dans un registre, par exemple, plutôt qu'en mémoire.)
Pour les types de classe, les problèmes sont un peu plus complexes, en raison du fait que vous pouvez appeler des fonctions membres sur une rvalue. Cela signifie que rvalues doit en fait avoir des adresses, pour le
this
pointeur, et peut être qualifié cv, puisque la qualification cv joue un rôle dans la résolution de surcharge. Enfin, C ++ 11 introduit plusieurs nouvelles distinctions, afin de prendre en charge les références rvalue; ceux-ci sont également principalement applicables aux types de classe.La promotion intégrale fait référence au fait que lorsque des types intégraux plus petits que un
int
sont utilisés comme valeurs r dans une expression, dans la plupart des contextes, ils seront promus versint
. Donc, même si j'ai une variable déclaréeshort a, b;
, dans l'expressiona + b
, les deuxa
etb
sont promusint
avant que l'ajout ne se produise. De même, si j'écrisa < 0
, la comparaison se fait sur la valeur dea
, convertie en unint
. Dans la pratique, il y a très peu de cas où cela fait une différence, au moins sur les compléments à 2 machines où l'arithmétique entière s'enroule (c'est-à-dire tous les exotiques sauf très peu, aujourd'hui - je pense que les mainframes Unisys sont les seules exceptions qui restent). Pourtant, même sur les machines les plus courantes:devrait donner des résultats différents: le premier est l'équivalent de
sizeof( short )
, le secondsizeof( int )
(en raison de la promotion intégrale).Ces deux problèmes sont formellement orthogonaux; rvalues et lvalues n'ont rien à voir avec la promotion intégrale. Sauf que ... la promotion intégrale ne s'applique qu'aux valeurs r, et la plupart (mais pas tous) des cas où vous utiliseriez une rvalue entraîneront une promotion intégrale. Pour cette raison, il n'y a vraiment aucune raison de renvoyer une valeur numérique dans quelque chose de plus petit que
int
. Il y a même une très bonne raison de ne pas le renvoyer comme type de caractère. Les opérateurs surchargés, comme<<
, se comportent souvent différemment pour les types de caractères, vous souhaitez donc uniquement renvoyer des caractères sous forme de types de caractères. (Vous pouvez comparer la différence:La différence est que dans le second cas, l'ajout a provoqué une promotion intégrale, ce qui entraîne une surcharge différente de
<<
à choisir.la source
return values are rvalues, subject to integral promotion
dans votre réponse.signed char
? Se comporterait-il de la même manière qu'un signechar
ou serait-il d'un type différent?Il est intentionnel qu'il ne renvoie pas -1, 0 ou 1.
Cela permet (notez que ce n'est pas pour les chaînes, mais cela s'applique également aux chaînes)
ce qui est beaucoup moins encombrant que:
c'est ce que vous auriez à faire [ou quelque chose du genre] si vous devez renvoyer -1, 0 ou 1.
Et cela fonctionne aussi pour les types plus complexes:
Dans le cas des chaînes, nous pouvons faire ceci:
la source
compare
fonction a des problèmes de débordement qui (heureusement) ne s'appliquent pas également si elle prendchar*
etchar
est inférieure àint
. Par exemple, si*a
estMAX_INT
et*b
est-1
alors*a - *b
est UB, mais si l'implémentation choisit de définir son comportement alors le résultat est presque certainement négatif.length()
renvoie asize_t
, qui peut être plus grand queint
…int est généralement (c'est-à-dire sur la plupart des matériels modernes) un entier de la même taille que le bus système et / ou les registres cpu, ce qu'on appelle le mot machine. Par conséquent, int est généralement transmis plus rapidement que les types plus petits, car il ne nécessite pas d'alignement, de masquage et d'autres opérations.
Les types plus petits existent principalement pour permettre l'optimisation de l'utilisation de la RAM pour les tableaux et les structures. Dans la plupart des cas, ils échangent quelques cycles CPU (sous forme d'opérations d'alignement) pour une meilleure utilisation de la RAM.
À moins que vous n'ayez besoin de forcer votre valeur de retour à être un nombre signé ou non signé d'une taille de centain (char, short…), il vaut mieux utiliser int, c'est pourquoi la bibliothèque standard le fait.
la source
C'est un C-isme.
Lorsque C exigeait des
compare
fonctions de type -type, elles renvoyaient toujours un fichierint
. C ++ vient de faire avancer cela (malheureusement).Cependant, renvoyer un
int
est probablement le moyen le plus rapide, car il s'agit généralement de la taille des registres du système utilisé. (Délibérément vague.)la source
short
etchar
peut imposer des pénalités de performance, par exemple255+7
a une valeur différente pour achar
et anint
donc une implémentation correcte ne peut pas nécessairement simplement stocker unchar
endroit où unint
peut aller sans se soucier de remettre sa sémantique. Les compilateurs n'optimiseront pas nécessairement l'inefficacité que cela impose.La méthode ne renvoie pas réellement un entier dans l'ensemble
{ -1, 0, 1 }
; il peut en fait s'agir de n'importe quelle valeur intégrale.Pourquoi? La principale raison à laquelle je peux penser est que
int
c'est censé être la valeur «grandeur nature» de l'architecture; les opérations sur des valeurs de cette taille sont généralement au moins aussi rapides (et dans de nombreux cas plus rapides) que les opérations sur des valeurs plus petites ou plus grandes. Il s'agit donc de laisser une mise en œuvre suffisamment lâche pour utiliser ce qui est le plus rapide.la source
Ce serait une bonne idée. Une meilleure façon serait de retourner un bool (si seulement vous voulez comparer si égal), ou enum (pour plus d'informations):
la source
Supposons que certaines personnes changent un code de C à C ++. Ils ont décidé de remplacer
strcmp
àstring::compare
.Depuis les
strcmp
retoursint
, il est plus facile destring::compare
revenirint
, en cadeau.la source
Probablement pour le faire fonctionner plus comme
strcmp
qui a également cet ensemble de valeurs de retour . Si vous vouliez porter du code, il serait probablement plus intuitif d'avoir des remplacements aussi proches que possible.En outre, la valeur de retour n'est pas simplement
-1
,0
ou1
mais<0
,0
ou>0
.De plus, comme cela a été mentionné, puisque le retour fait l'objet d' une promotion intégrale, il n'est pas logique de le réduire.
la source
car une valeur de retour booléenne ne peut être que deux valeurs possibles (vrai, faux) et une fonction de comparaison peut renvoyer trois valeurs possibles (inférieure à, égale, supérieure à).
Mettre à jour
Bien qu'il soit certainement possible de renvoyer un short signé, si vous vouliez vraiment implémenter votre propre fonction de comparaison, vous pouvez renvoyer une valeur nibble ou struct avec deux booléens.
la source
short
etchar
comme alternatives àint
.