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.
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!
Std::string::compare() renvoie un int
:
- égal à zéro si
s
ett
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 .
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).
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).
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.
compare()
est équivalent à strcmp(). {[1] } est une vérification d'égalité simple. compare()
donc retourne un int
, ==
est un booléen.
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.
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; }
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.
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.