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.
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!
std :: string :: compare () retourne une int
:
s
et t
sont égaux,s
est inférieur à t
,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 .
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).
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).
compare()
est équivalent à strcmp (). ==
est une vérification d'égalité simple. compare()
renvoie donc une int
, ==
est un booléen.
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.
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.
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; }
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.
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.