web-dev-qa-db-fra.com

Différences entre la chaîne C++ == et compare ()?

Je viens de lire quelques recommandations sur l'utilisation 

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 que cela 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 privilégiée?

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

293
Klaim

C’est ce que dit la norme sur 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;

Retourne: lhs.compare (rhs) == 0.

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

370
Bo Persson

std :: string :: compare () retourne une 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érieur à t.

Si vous voulez que votre premier extrait de code soit équivalent au second, vous devez lire:

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

L'opérateur d'égalité ne teste que l'égalité (d'où son nom) et renvoie une bool.

Pour plus de détails sur les cas d'utilisation, compare() peut être utile si vous souhaitez savoir comment les deux chaînes se lient l'une à l'autre (plus ou moins) lorsqu'elles se révèlent différentes. PlasmaHH mentionne à juste titre des arbres, et il pourrait également s'agir, par exemple, d'un algorithme d'insertion de chaîne visant à garder le conteneur trié, d'un algorithme de recherche dichotomique pour le conteneur susmentionné, etc.

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

113
Frédéric Hamidi

compare a des surcharges pour comparer les sous-chaînes. Si vous comparez des chaînes entières, vous devez simplement utiliser l'opérateur == (et le fait qu'il appelle compare ou non est à peu près inutile).

28
Cat Plus Plus

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

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

FYI, j'ai couru 1 000 000 itérations afin de parvenir à une telle conclusion.

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

DEBUG BUILD

string :: operator == ()

        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)  

string :: compare ()

            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 (add esp, 8 et movzx edx, al) 

RELEASE BUILD

string :: operator == ()

        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)  

string :: compare ()

            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 l'optimisation.

Enfin, à mon avis, le gain de performance est négligeable. Par conséquent, je laisserais vraiment au développeur le soin de choisir celui qui est préféré, car les deux permettent d’obtenir le même résultat (surtout lorsqu’il s’agit de la version finale).

23
Tony Mulia

compare() est équivalent à strcmp (). == est une vérification d'égalité simple. compare() renvoie donc une int, == est un booléen.

5
ckruse

compare() retournera false (ainsi, 0) si les chaînes sont égales.

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

Utilisez ce qui rend le code plus lisible.

5
Luchian Grigore

Si vous voulez seulement vérifier l’égalité des chaînes, utilisez l’opérateur ==. Déterminer si deux chaînes sont égales est plus simple que de trouver un ordre (ce qui est ce que compare () donne,) de sorte qu'il pourrait être plus performant dans votre cas d'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 l'égalité des chaînes, utilisez donc l'opérateur d'égalité (pour que vos attentes et celles des développeurs de la bibliothèque s'alignent.) Si les performances sont importantes, vous souhaiterez peut-être tester les deux méthodes et rechercher la plus rapide.

3
RobH

Une chose qui n’est pas couverte ici est que cela dépend si on compare chaîne à c chaîne, chaîne c à chaîne ou chaîne à chaîne.

Une différence majeure réside dans le fait que pour comparer la taille de deux chaînes est vérifiée avant d'effectuer la comparaison, l'opérateur == est plus rapide qu'une comparaison.

voici la comparaison que je 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
Dragos

Supposons que l'on considère deux chaînes s et t.
Donnez-leur des valeurs.
Lorsque vous les comparez avec (s == t) , cela retourne une valeur booléenne (vrai ou faux, 1 ou 0).
Mais lorsque vous comparez avec s.compare (t) , l'expression renvoie une valeur
(i) 0 - si s et t sont égaux
(ii) <0 - soit si la valeur du premier caractère non apparié dans s est inférieure à celle de t ou si la longueur de s est inférieure à celle de t.
(iii)> 0 - soit si la valeur du premier caractère non apparié dans t est inférieure à celle de s ou si la longueur de t est inférieure à celle de s. 

0
narutoUzumaki21

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

retourne vrai.

somestring.compare("") 

retour 1, et

somestring=="" 

return: no operator "==" correspond à ces opérandes.

somestring.c_str()==""

return: Une erreur non spécifiée s'est produite.

0
Frank