c++ - Diferencia entre la cadena+= s1 y la cadena=cadena+s1
performance stdstring (4)
Para
los tipos incorporados
a += b
es exactamente lo mismo que
a = a + b
, pero para las clases, esos operadores están sobrecargados y llaman a diferentes funciones.
En su ejemplo,
fans = fans + s[i]
crea una cadena temporal y la asigna (mueve) a los
fans
, pero los
fans += s[i]
no crean esa temporal, por lo que puede ser más rápido.
Uno de mis programas excede el límite de tiempo cuando uso
fans = fans + s[i]
, mientras que cuando uso
fans += s[i]
, se está aceptando ... ¿Por qué sucede esto?
Para explicar más, los fanáticos son una cadena y s también es una cadena, así que mientras iteramos sobre la cadena, quiero solo algunos caracteres de s, así que estoy creando una nueva cadena. Ahora hay dos maneras en las que puedo agregar caracteres a mi nueva cadena. aficionados.
El problema se menciona a continuación.
fans = fans + s[i]; // gives Time limit exceeded
fans += s[i]; // runs successfully
Para los tipos fundamentales,
a = a + b
y
a += b
significan lo mismo.
Para tipos de clase arbitrarios,
a = a + b
y
a += b
no están relacionados;
buscan diferentes operadores, y esos operadores pueden hacer cosas arbitrarias.
El
hecho de que
no estén
realmente
relacionados es el olor a código, un signo de un problema de diseño.
a = a + b
convierte en
operator=( a, operator+( a, b ) )
aproximadamente;
las reglas de búsqueda reales son un poco más complejas (involucran operadores miembros y operadores no miembros, y el hecho de que
=
no tiene un operador no miembro, etc.), pero ese es su núcleo.
a += b
convierte en
operator+=( a, b )
en un sentido similar.
Ahora, es un patrón común para implementar
+
en términos de
+=
;
Si haces esto, obtienes:
a = a + b
se convierte en
a = ((auto)(a) += b);
donde
(auto)
es el nuevo
c ++ 20
/
c ++ 23
"crear una copia temporal del argumento" característica.
Fundamentalmente,
a+=b
puede reutilizar el contenido de
a
directamente, mientras que
a = a + b
no puede;
en el momento
a+b
se evalúa a
a+b
, no se sabe que pronto se sobrescribirá.
Algunas bibliotecas tratan esto utilizando una técnica conocida como "plantillas de expresión";
a+b
no es un valor, sino una descripción en tiempo de compilación de la expresión
a+b
, que cuando se asigna a
a
se usa para rellenar
a
con datos.
Con las plantillas de expresión, se elimina el problema fundamental de
a+=b
sabe más que
a=a+b
.
Ahora, para
std::string
específicamente,
a+b
crea un objeto de cadena temporal, luego
a=(a+b)
mueve a
a
(puede reutilizar el búfer del objeto de cadena temporal o el búfer de
a
, el estándar es silencio sobre este asunto).
a+=b
debe reutilizar cualquier exceso de capacidad en
a
búfer.
Así que si
a.reserve(1<<30)
(1 billón),
a+=b
no puede asignar más.
Si usa
fans=fans+s[i]
, la cadena se copiará en cada paso de bucle.
El nuevo elemento se agregará a la copia de la cadena y el resultado se reasignará a los
fans
variables.
Después de esto, la cadena antigua tendrá que eliminarse porque ya no se hace referencia.
Esto lleva mucho tiempo.
Si usa los
fans+=s[i]
asignación aumentada
fans+=s[i]
la cadena no se copiará en cada paso de bucle y no es necesario eliminar la variable de referencia ya que aquí no hay ninguna variable de referencia.
Esto ahorra mucho tiempo.
Espero que ahora puedas entender !!
std::string
tiene miembros
operator +
y
operator +=
.
El primero se implementa generalmente con el segundo por medio de un intermedio temporal.
Mirando efectivamente algo como esto (verifique su fuente de implementación si quiere saber exactamente lo que hace el suyo):
/// note reference return type
std::string& operator +=(char c)
{
this->append(c);
return *this;
}
// note value return type
std::string operator +(char c) const
{
std::string tmp = *this;
tmp += c; // or just tmp.append(c) directly
return tmp;
}
La configuración de
tmp
es costosa.
La función general puede (y generalmente se hace) mejor con la semántica de
asignación de movimientos
al destino final en el lado de la persona que llama, pero el gasto de la temporaria es, sin embargo, aún allí.
Hazlo unas cuantas veces y no notarás la diferencia.
Hágalo miles, o millones, etc. de veces, y puede significar un
mundo
de diferencia.