resueltos - funciones en c++ pdf
Diferencias entre la cadena de C++== y compare()? (10)
En el depurador de Visual Studio 2012, solo lo siguiente funciona correctamente cuando se comprueba que una cadena está vacía o no:
strcmp(somestring.c_str(),"")==0
volver verdadero
somestring.compare("")
devuelve 1, y
somestring==""
return: ningún operador "==" coincide con estos operandos.
somestring.c_str()==""
retorno: Ha ocurrido un error no especificado.
Acabo de leer algunas recomendaciones sobre el uso
std::string s = get_string();
std::string t = another_string();
if( !s.compare(t) )
{
en lugar de
if( s == t )
{
Casi siempre uso el último porque estoy acostumbrado y se siente natural, más legible. Ni siquiera sabía que existía una función de comparación separada. Para ser más precisos, pensé que == llamaría compare ().
¿Cuáles son las diferencias? ¿En qué contextos se debe favorecer de un modo a otro?
Estoy considerando solo los casos en los que necesito saber si una cadena tiene el mismo valor que otra cadena.
Esto es lo que la norma tiene que decir sobre el operator==
21.4.8.2 operador ==
template<class charT, class traits, class Allocator>
bool operator==(const basic_string<charT,traits,Allocator>& lhs,
const basic_string<charT,traits,Allocator>& rhs) noexcept;
Devoluciones: lhs.compare (rhs) == 0.
Parece que no hay mucha diferencia!
Internamente, string :: operator == () está usando string :: compare (). Consulte: CPlusPlus - String :: Operator == ()
Escribí una pequeña aplicación para comparar el rendimiento, y al parecer, si compilas y ejecutas tu código en un entorno de depuración, String :: compare () es un poco más rápido que string :: operator == (). Sin embargo, si compilas y ejecutas tu código en el entorno Release, ambos son prácticamente iguales.
Para su información, corrí 1,000,000 iteraciones para llegar a tal conclusión.
Para demostrar por qué en el entorno de depuración la cadena :: compare es más rápida, fui al ensamblaje y aquí está el código:
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)
Puedes ver que en string :: operator == (), tiene que realizar operaciones adicionales (add esp, 8 y movzx edx, al)
Construcción de liberación
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)
Ambos códigos de ensamblaje son muy similares a como el compilador realiza la optimización.
Finalmente, en mi opinión, la ganancia de rendimiento es insignificante, por lo que realmente dejaría que el desarrollador decidiera cuál es el preferido, ya que ambos logran el mismo resultado (especialmente cuando se trata de la versión de lanzamiento).
Si solo desea verificar la igualdad de cadenas, use el operador ==. Determinar si dos cadenas son iguales es más sencillo que encontrar un pedido (que es lo que compara () da), por lo que podría ser mejor en términos de rendimiento utilizar su operador de igualdad.
Respuesta más larga: la API proporciona un método para verificar la igualdad de cadenas y un método para verificar el orden de las cadenas. Desea la igualdad de cadenas, así que use el operador de igualdad (para que sus expectativas y las de los implementadores de la biblioteca se alineen). Si el rendimiento es importante, le gustaría probar ambos métodos y encontrar el más rápido.
Supongamos que consideramos dos cadenas s y t.
Dales algunos valores.
Cuando los compara con (s == t) , devuelve un valor booleano (verdadero o falso, 1 o 0).
Pero cuando se compara con s.compare (t) , la expresión devuelve un valor
(i) 0 - si s y t son iguales
(ii) <0 - ya sea si el valor del primer carácter no coincidente en s es menor que el de t o la longitud de s es menor que la de t.
(iii) > 0 : ya sea si el valor del primer carácter no coincidente en t es menor que el de s o la longitud de t es menor que la de s.
Una cosa que no se cubre aquí es que depende si comparamos la cadena con la cadena c, la cadena c con la cadena o la cadena con la cadena.
Una diferencia importante es que para comparar dos cadenas, la igualdad de tamaño se comprueba antes de realizar la comparación y eso hace que el operador == sea más rápido que una comparación.
Aquí está la comparación como la veo en 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; }
std::string::compare() devuelve un int
:
- igual a cero si
s
yt
son iguales, - menor que cero si
s
es menor quet
, - mayor que cero si
s
es mayor quet
.
Si desea que su primer fragmento de código sea equivalente al segundo, debería leer:
if (!s.compare(t)) {
// ''s'' and ''t'' are equal.
}
El operador de igualdad solo prueba la igualdad (de ahí su nombre) y devuelve un bool
.
Para profundizar en los casos de uso, compare()
puede ser útil si está interesado en cómo las dos cadenas se relacionan entre sí (menos o más) cuando son diferentes. PlasmaHH menciona correctamente los árboles, y también podría ser, digamos, un algoritmo de inserción de cadenas que apunta a mantener el contenedor ordenado, un algoritmo de búsqueda dicotómica para el contenedor mencionado anteriormente, etc.
EDITAR: Como Steve Jessop señala en los comentarios, compare()
es más útil para los algoritmos de búsqueda binaria y ordenación rápida. Se pueden implementar clasificaciones naturales y búsquedas dicotómicas con solo std::less .
compare()
devolverá false
(bueno, 0
) si las cadenas son iguales.
Así que no tomes el intercambio de uno por otro a la ligera.
Use lo que haga que el código sea más legible.
compare()
es equivalente a strcmp (). ==
es simple comprobación de igualdad. compare()
por lo tanto devuelve un int
, ==
es un booleano.
compare
tiene sobrecargas para comparar subcadenas. Si está comparando cadenas enteras, debería usar el operador ==
(y si las compare
llamadas son o no bastante irrelevantes).