102 votes

Pourquoi est-String.compare retourne un int ?

Pourquoi est - string::compare retourner un int au lieu d'un type plus petit, comme short ou char? Ma compréhension est que cette méthode ne renvoie -1, 0 ou 1.

Deuxième partie, si j'étais à la conception d'une méthode de comparaison qui compare deux objets de type Foo et je ne voulais retourner -1, 0 ou 1, à l'aide de short ou char généralement une bonne idée?

EDIT: j'ai corrigé, string::compare ne renvoie -1, 0, ou 1, en fait, cela renvoie une valeur >0, <0 ou 0. Merci de me garder en ligne les gars.

Il semble que la réponse est à peu près, il n'y a pas de raison de revenir un type plus petit que int, car les valeurs de retour sont "rvalues" et ceux "rvalues" ne bénéficient pas de plus petit étant de type int (4 octets). Aussi, de nombreuses personnes ont souligné que les registres de la plupart des systèmes sont probablement va être de la taille de l'int de toute façon, puisque ces registres vont être remplis si vous leur donnez un 1, 2 ou 4 octets de la valeur, il n'y a pas de réel avantage à retourner une valeur plus petite.

EDIT 2: En fait, il semble qu'il y ait peut-être supplémentaire de traitement lors de l'utilisation de petits types de données telles que l'alignement, le masquage, etc. Le consensus général est que le plus petit des types de données existent pour économiser de la mémoire lorsque vous travaillez avec un grand nombre de données, comme dans le cas d'un tableau.

Appris quelque chose aujourd'hui, merci encore les gars!

113voto

James Kanze Points 96599

D'abord, le cahier des charges est qu'il sera de retour d'une valeur de moins de que, égal ou supérieur à 0, pas nécessairement -1 ou 1. Deuxièmement, les valeurs de retour sont rvalues, sous réserve intégrale promotion, donc il n'y a pas de point dans le retour de quelque chose de plus petit.

EDIT:

Par demande, certains plus d'informations concernant les rvalues et promotion intégrale.

En C++ (comme en C), chaque expression est une rvalue ou un lvalue. Historiquement, les termes renvoient au fait que les lvalues apparaissent sur la gauche d'une affectation, où que rvalues ne peut apparaissent sur la droite. Aujourd'hui, un simple rapprochement pour non-types de classe est une lvalue a une adresse en mémoire, un rvalue ne l'est pas. Ainsi, vous ne pouvez pas prendre l'adresse d'une rvalue, et cv-qualificatifs (condition "accès") ne s'appliquent pas. Dans C++ termes, une rvalue qui n'a pas de type de classe est un pur valeur, pas un objet. La valeur de retour d'une fonction est une rvalue, sauf si elle a le type de référence. (Non-classe de types de ajustement dans un registre sera presque toujours être retournés dans un registre, par exemple, plutôt que dans la mémoire.)

Pour les types de classe, les questions sont un peu plus complexes, en raison de la fait que vous pouvez appeler des fonctions de membre sur une rvalue. Cette signifie que rvalues doit en effet disposer d'adresses, pour l' this pointeur, et peut être de cv qualifiés, depuis le cv-qualification joue un rôle dans la résolution de surcharge. Enfin, C++11 introduit plusieurs nouvelles distinctions, à l'appui de références rvalue; ceux-ci, aussi, sont principalement applicables aux types de classe.

Promotion intégrale se réfère au fait que, lorsque les types intégraux plus petit qu'un int sont utilisés comme des rvalues dans une expression, dans la plupart des contextes, ils seront promus en int. Donc, même si J'ai une variable déclarée short a, b;, dans l'expression a + b, les deux a et b sont promues int avant l'addition se produit. De même, si j'écris a < 0, la comparaison est faite sur la valeur de a, convertis en int. Dans la pratique, il n' très peu de cas où cela fait une différence, au moins sur 2 complète les machines où l'arithmétique des nombres entiers d'enveloppe (c'est à dire tous, mais très peu d'espèces exotiques, aujourd'hui—je pense que le Unisys les mainframes sont les seules exceptions à gauche). Encore, même sur le plus commun des machines:

short a = 1;
std::cout << sizeof( a ) << std::endl;
std::cout << sizeof( a + 0 ) << std::endl;

devrait donner des résultats différents: le premier est l'équivalent de sizeof( short ), le deuxième sizeof( int ) (en raison de promotion intégrale).

Ces deux questions sont formellement orthogonale; rvalues et lvalues n'ont rien à voir avec la promotion intégrale. Sauf... partie intégrante de la promotion s'applique uniquement aux rvalues, et la plupart (mais pas en tout cas où vous utiliseriez une rvalue entraînera promotion intégrale. Pour cette raison, il n'y a vraiment pas de raison de pour retourner 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 retourner comme un type de caractère. Opérateurs surchargés, comme <<, se comportent souvent différemment pour les types de caractères, de sorte que vous ne voulez retourner les personnages comme les types de caractères. (Vous pouvez comparer les différence:

char f() { return 'a'; }
std::cout << f() << std::endl;      //  displays "a"
std::cout << f() + 0 << std::endl;  //  displays "97" on my machine

La différence est que dans le second cas, le plus a causé promotion intégrale de se produire, ce qui entraîne dans un autre la surcharge de l' << d'être choisi.

41voto

Mats Petersson Points 70074

C'est à dessein qu'il n'a pas de retour -1, 0 ou 1.

Il permet (notez que ce n'est pas pour les cordes, mais il s'applique également aux chaînes de caractères)

int compare(int *a, int *b)
{
   return *a - *b;
}

ce qui est beaucoup moins encombrant que:

int compare(int *a, int *b)
{
   if (*a == *b) return 0;
   if (*a > *b) return 1;
   return -1;
}

qui est ce que vous avez à faire [ou quelque chose le long de ces lignes] si vous avez à retourner -1, 0 ou 1.

Et cela fonctionne pour les types plus complexes, trop:

class Date
{
    int year;
    int month;
    int day;
}

int compare(const Date &a, const Date &b)
{
   if (a.year != b.year) return a.year - b.year;
   if (a.month != b.month) return a.month - b.month;
   return a.day - b.day;
}

Dans la chaîne de cas, nous pouvons faire ceci:

int compare(const std::string& a, const std::string& b)
{
   int len = min(a.length(), b.length());

   for(int i = 0; i < len; i++)
   {
      if (a[i] != b[i]) return a[i] - b[i];
   }
   // We only get here if the string is equal all the way to one of them
   // ends. If the length isn't equal, "longest" wins. 
   return a.length() - b.length();
}

25voto

Tobia Points 2978

int est généralement (ce qui signifie la plupart du matériel moderne) un entier de la même taille que le système de bus et/ou les registres du cpu, ce qui est appelé la machine de parole. Donc int est généralement transmis plus rapidement que les plus petits types, car il n'a pas besoin d'alignement, de masquage et d'autres opérations.

Les plus petits types existent principalement pour permettre l'utilisation de la RAM de l'optimisation pour les tableaux et les structures. Dans la plupart des cas, ils échangent quelques cycles CPU (sous la forme de aligment d'exploitation) pour une meilleure utilisation de la RAM.

Sauf si vous avez besoin d'appliquer votre valeur de retour d'être signé ou non signé nombre d'une centain taille (char, short...) vous êtes mieux d'utiliser int, qui est pourquoi la bibliothèque standard de fait.

10voto

Alex Chamberlain Points 2851

C'est un C-ism.

Lorsque C nécessite compare -type fonctions, ils retournent toujours un int . C ++ vient de porter ça (malheureusement).

Cependant, retourner le int est probablement le moyen le plus rapide, car il correspond généralement à la taille des registres du système utilisé. (Délibérément vague.)

10voto

Jon Points 194296

La méthode ne renvoie pas un nombre entier dans l'ensemble { -1, 0, 1 } ; il peut en fait être n'importe quelle valeur intégrale.

Pourquoi? La principale raison à laquelle je peux penser est que int est censé être la valeur de "taille naturelle" pour 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 permettre à l’implémentation de disposer de suffisamment de temps pour utiliser ce qui est le plus rapide.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X