¿La expresión de encadenamiento de std::string en el código de Bjarne Stroustrup exhibe un comportamiento indefinido?
En la cuarta edición de "El lenguaje de programación C" de Bjarne Stroustrup , un fragmento de código ejemplifica el encadenamiento usando el reemplazo de std::string método:
void f2() {
std::string s = "but I have heard it works even if you don't believe in it";
s.replace(0, 4, "").replace(s.find("even"), 4, "only").replace(s.find(" don't"), 6, "");
assert(s == "I have heard it works only if you believe in it");
}
Este código, sin embargo, exhibe comportamiento no especificado en lugar de invocar un comportamiento indefinido.
La razón de este comportamiento no especificado radica en el orden de evaluación, que no está especificado para subexpresiones de llamadas a funciones encadenadas. En este caso, las llamadas a la función s.find se evalúan antes o después de la primera llamada a s.replace, lo que altera la longitud de la cadena resultante y afecta el resultado de la llamada de búsqueda posterior.
El ejemplo de la pregunta demuestra esto: cuando se evalúa por diferentes compiladores (clang, gcc), se obtienen resultados diferentes debido a diferentes evaluaciones pedidos.
Detalles
Los argumentos de función tienen un orden de evaluación no especificado y, aunque el encadenamiento de llamadas a función introduce un orden de evaluación de izquierda a derecha para cada invocación de función, los argumentos de cada llamada se secuencian solo antes de con respecto a esa llamada de función en particular.
En el ejemplo, esta indeterminación surge en la evaluación de s.find("even") y s.find(" don't") con respecto a s.replace(0, 4, "").
Ignorando más desgloses de subexpresiones, la secuencia de Los pasos de evaluación y su interdependencia se pueden representar de la siguiente manera:
Step 1: s.replace(0, 4, "") // A Step 2: s.find("even") // B Step 3: s.replace(B, 4, "only") // C Step 4: s.find("don't") // D Step 5: s.replace(D, 6, "") // E
Si bien A se secuencia antes que B, que a su vez se secuencia antes de C, no existe ninguna relación de secuenciación entre B y D con respecto a A. Como resultado, D puede evaluarse antes o después de A, lo que lleva a diferentes resultados según la secuencia elegida.
C 17 Cambios
El estándar C 17 fortalece el orden de las reglas de evaluación para expresiones postfix y su lista de expresiones, dando al código en cuestión un comportamiento bien especificado. La secuenciación es la siguiente:
Por lo tanto, en C 17 y posteriores, este código siempre se evaluará correctamente.
Descargo de responsabilidad: Todos los recursos proporcionados provienen en parte de Internet. Si existe alguna infracción de sus derechos de autor u otros derechos e intereses, explique los motivos detallados y proporcione pruebas de los derechos de autor o derechos e intereses y luego envíelos al correo electrónico: [email protected]. Lo manejaremos por usted lo antes posible.
Copyright© 2022 湘ICP备2022001581号-3