Différences entre C++ string = = et compare()?

Je viens de lire quelques recommandations sur l'utilisation de

std::string s = get_string();
std::string t = another_string();

if( !s.compare(t) ) 
{

Au Lieu de

if( s == t )
{

J'utilise presque toujours le dernier parce que j'y suis habitué et qu'il semble naturel, plus lisible. Je ne savais même pas qu'il y avait une fonction de comparaison séparée. Pour être plus précis, je pensais que = = appellerait compare ().

Quelles sont les différences? Dans quels contextes une voie devrait-elle être favorisée à l'autre?

Je ne considère que les cas où j'ai besoin de savoir si une chaîne est la même valeur qu'une autre chaîne.

269
demandé sur sehe 2012-02-06 14:44:00

10 réponses

C'est ce que la norme a à dire à propos de operator==

21.4.8.2 opérateur==

template<class charT, class traits, class Allocator>
bool operator==(const basic_string<charT,traits,Allocator>& lhs,
                const basic_string<charT,traits,Allocator>& rhs) noexcept;

Renvoie: lhs.comparer(rhs) == 0.

On dirait qu'il n'y a pas beaucoup de différence!

334
répondu Bo Persson 2017-08-06 17:10:34

Std::string::compare() renvoie un int:

  • égal à zéro si s et t sont égaux,
  • inférieur à zéro si s est inférieur à t,
  • supérieur à zéro si s est supérieure à t.

Si vous voulez que votre premier extrait de code soit équivalent au second, il devrait en fait lire:

if (!s.compare(t)) {
    // 's' and 't' are equal.
}

L'opérateur d'égalité teste uniquement l'égalité (d'où son nom) et renvoie un bool.

Pour élaborer sur le les cas d'utilisation, compare() peuvent être utiles si vous êtes intéressé par la façon dont les deux chaînes se rapportent les unes aux autres (moins ou plus) quand elles sont différentes. PlasmaHH mentionne à juste titre des arbres, et il pourrait aussi s'agir, par exemple, d'un algorithme d'insertion de chaîne qui vise à garder le conteneur trié, d'un algorithme de recherche dichotomique pour le conteneur susmentionné, etc.

EDIT: {[31] } Comme le souligne Steve Jessop dans les commentaires, compare() est le plus utile pour le tri rapide et les algorithmes de recherche binaire. Les tris naturels et les recherches dichotomiques peuvent être implémentés avec seulement std:: less .

102
répondu Frédéric Hamidi 2012-02-06 12:07:42

compare a des surcharges pour comparer les sous-chaînes. Si vous comparez des chaînes entières, vous devriez simplement utiliser l'opérateur == (et si elle appelle compare ou non est à peu près hors de propos).

26
répondu Cat Plus Plus 2012-02-06 10:47:08

En interne, string:: operator = = () utilise string::compare(). Veuillez vous référer à: CPlusPlus - String:: opérateur==()

J'ai écrit une petite application pour comparer les performances, et apparemment si vous compilez et exécutez votre code sur l'environnement de Débogage, String::compare() est légèrement plus rapide que string::operator==(). Cependant, si vous compilez et exécutez votre code dans L'environnement de publication, les deux sont à peu près les mêmes.

POUR INFO, j'ai couru 1,000,000 itération afin de venir avec une telle conclusion.

Afin de prouver pourquoi dans l'environnement de débogage de la chaîne::comparer est plus rapide, je suis allé à l'assemblée et voici le code:

DÉBOGAGE CONSTRUIRE

chaîne:: opérateur==()

        if (str1 == str2)
00D42A34  lea         eax,[str2]  
00D42A37  push        eax  
00D42A38  lea         ecx,[str1]  
00D42A3B  push        ecx  
00D42A3C  call        std::operator==<char,std::char_traits<char>,std::allocator<char> > (0D23EECh)  
00D42A41  add         esp,8  
00D42A44  movzx       edx,al  
00D42A47  test        edx,edx  
00D42A49  je          Algorithm::PerformanceTest::stringComparison_usingEqualOperator1+0C4h (0D42A54h)  

chaîne:: comparer()

            if (str1.compare(str2) == 0)
00D424D4  lea         eax,[str2]  
00D424D7  push        eax  
00D424D8  lea         ecx,[str1]  
00D424DB  call        std::basic_string<char,std::char_traits<char>,std::allocator<char> >::compare (0D23582h)  
00D424E0  test        eax,eax  
00D424E2  jne         Algorithm::PerformanceTest::stringComparison_usingCompare1+0BDh (0D424EDh)

Vous pouvez voir que dans string::operator== (), il doit effectuer des opérations supplémentaires (ajouter esp, 8 et movzx edx,al)

Libération Construire

chaîne:: opérateur==()

        if (str1 == str2)
008533F0  cmp         dword ptr [ebp-14h],10h  
008533F4  lea         eax,[str2]  
008533F7  push        dword ptr [ebp-18h]  
008533FA  cmovae      eax,dword ptr [str2]  
008533FE  push        eax  
008533FF  push        dword ptr [ebp-30h]  
00853402  push        ecx  
00853403  lea         ecx,[str1]  
00853406  call        std::basic_string<char,std::char_traits<char>,std::allocator<char> >::compare (0853B80h)  

chaîne:: comparer()

            if (str1.compare(str2) == 0)
    00853830  cmp         dword ptr [ebp-14h],10h  
    00853834  lea         eax,[str2]  
    00853837  push        dword ptr [ebp-18h]  
    0085383A  cmovae      eax,dword ptr [str2]  
    0085383E  push        eax  
    0085383F  push        dword ptr [ebp-30h]  
    00853842  push        ecx  
00853843  lea         ecx,[str1]  
00853846  call        std::basic_string<char,std::char_traits<char>,std::allocator<char> >::compare (0853B80h)

Les deux codes d'assemblage sont très similaires car le compilateur effectue une optimisation.

Enfin, à mon avis, Le gain de performance est négligeable, donc je laisserais vraiment au développeur de décider lequel est le préféré car les deux atteignent le même résultat (surtout quand il s'agit de la version release).

20
répondu Tony Mulia 2015-12-22 05:12:22

compare() sera de retour false (bien, 0) si les chaînes sont égales.

Alors ne prenez pas l'échange de l'un pour l'autre à la légère.

Utilisez ce qui rend le code plus lisible.

5
répondu Luchian Grigore 2012-02-06 10:48:47

compare() est équivalent à strcmp(). {[1] } est une vérification d'égalité simple. compare() donc retourne un int, == est un booléen.

4
répondu ckruse 2012-02-06 10:47:48

Si vous voulez juste vérifier l'égalité de chaîne, utilisez l'opérateur==. Déterminer si deux chaînes sont égales est plus simple que de trouver un ordre (ce que compare () donne), donc pourrait être meilleur dans votre cas pour utiliser l'opérateur d'égalité.

Réponse plus longue: L'API fournit une méthode pour vérifier l'égalité des chaînes et une méthode pour vérifier l'ordre des chaînes. Vous voulez une égalité de chaîne, utilisez donc l'opérateur d'égalité (de sorte que vos attentes et celles du les implémenteurs de bibliothèque s'alignent.) Si la performance est importante, vous pouvez tester les deux méthodes et trouver le plus rapide.

2
répondu RobH 2012-02-06 11:16:06

Une chose qui n'est pas couverte ici est que cela dépend si nous comparons string à c string, c string à string ou string à string.

Une différence majeure est que pour comparer deux chaînes, l'égalité de taille est vérifiée avant de faire la comparaison et cela rend l'opérateur = = plus rapide qu'une comparaison.

Voici la comparaison telle que je la vois sur G++ Debian 7

// operator ==
  /**
   *  @brief  Test equivalence of two strings.
   *  @param __lhs  First string.
   *  @param __rhs  Second string.
   *  @return  True if @a __lhs.compare(@a __rhs) == 0.  False otherwise.
   */
  template<typename _CharT, typename _Traits, typename _Alloc>
    inline bool
    operator==(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
           const basic_string<_CharT, _Traits, _Alloc>& __rhs)
    { return __lhs.compare(__rhs) == 0; }

  template<typename _CharT>
    inline
    typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value, bool>::__type
    operator==(const basic_string<_CharT>& __lhs,
           const basic_string<_CharT>& __rhs)
    { return (__lhs.size() == __rhs.size()
          && !std::char_traits<_CharT>::compare(__lhs.data(), __rhs.data(),
                            __lhs.size())); }

  /**
   *  @brief  Test equivalence of C string and string.
   *  @param __lhs  C string.
   *  @param __rhs  String.
   *  @return  True if @a __rhs.compare(@a __lhs) == 0.  False otherwise.
   */
  template<typename _CharT, typename _Traits, typename _Alloc>
    inline bool
    operator==(const _CharT* __lhs,
           const basic_string<_CharT, _Traits, _Alloc>& __rhs)
    { return __rhs.compare(__lhs) == 0; }

  /**
   *  @brief  Test equivalence of string and C string.
   *  @param __lhs  String.
   *  @param __rhs  C string.
   *  @return  True if @a __lhs.compare(@a __rhs) == 0.  False otherwise.
   */
  template<typename _CharT, typename _Traits, typename _Alloc>
    inline bool
    operator==(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
           const _CharT* __rhs)
    { return __lhs.compare(__rhs) == 0; }
1
répondu Dragos 2015-09-24 22:13:18

Dans le débogueur Visual Studio 2012, seuls les éléments suivants fonctionnent correctement lorsque vous vérifiez qu'une chaîne est vide ou non:

strcmp(somestring.c_str(),"")==0

Renvoie true.

somestring.compare("") 

Retour 1, et

somestring=="" 

Retour: aucun opérateur "= = " ne correspond à ces opérandes.

somestring.c_str()==""

Return: une erreur non spécifiée s'est produite.

0
répondu Frank 2017-07-24 13:19:04

Supposons que nous considérons deux chaînes s et t.
Leur donner certaines valeurs.
Lorsque vous les Comparez en utilisant (s==t) il renvoie une valeur booléenne (true ou false, 1 ou 0).
Mais lorsque vous comparez en utilisant s. compare(t) ,l'expression renvoie une valeur
(je) 0 - si s et t sont égaux
ii) - soit si la valeur du premier caractère non apparié dans s est inférieure à celle de t, soit si la longueur de s est inférieure à celle de t.
iii) >0 - soit si le la valeur du premier caractère non apparié dans t est inférieure à celle de s ou la longueur de t est inférieure à celle de S.

0
répondu narutoUzumaki21 2017-10-16 11:58:15