Mochis NoticiasTecnologíaDesventajas de utilizar una función C++ estándar «global»: su contraparte en C se puede camuflar
Mochis NoticiasTecnologíaDesventajas de utilizar una función C++ estándar «global»: su contraparte en C se puede camuflar
Tecnología

Desventajas de utilizar una función C++ estándar «global»: su contraparte en C se puede camuflar

Última actualización el 30 de septiembre de 2019

Una gran cantidad de funciones de C++ en la biblioteca estándar se extienden a partir de funciones de C estándar, como qsort(), memcpy(), etc. Entre estas funciones, muchas sobrecargaron a sus homólogos en C. Por ejemplo, abs() en C++ está sobrecargado tanto para tipos integrales como de punto flotante, mientras que solo está definido para int Cª. Sin embargo, estas funciones a menudo se utilizan indebidamente como funciones globales y producen resultados inesperados.

Las funciones de la biblioteca estándar de C++ generalmente se colocan en el espacio de nombres. std, incluidos aquellos que están extendidos por sus homólogos C. Por ejemplo, la función C sqrt() corresponde a std::sqrt() en C++. La siguiente función my_sqrt_1 calcula la raíz cuadrada del parámetro de entrada x:

#include <cmath>

float my_sqrt_1(float x) {
    return std::sqrt(x);
}

Sin embargo, de vez en cuando, la gente pierde su std:: prefijo, crees que es demasiado redundante. Por lo tanto, el fragmento de código anterior a menudo se abrevia como (usando la «versión global» de sqrt())

#include <cmath>
// no "using namespace std;"

float my_sqrt_2(float x) {
    return sqrt(x);
}

Si bien puede parecer un buen truco, es posible que no funcione como se esperaba. En C++, el comportamiento de llamar a una función estándar sin usar explícitamente el espacio de nombres std depende de la implementación: un compilador puede interpretar la función como la función C++ o su contraparte C. En el ejemplo anterior, my_sqrt_2 podría posiblemente cualquiera

  • él llamó float std::sqrt(float) con x como entrada y devolver su valor de retorno (este es el caso de x64 msvc v19.22 como se probó en C Compiler Explorer, o
  • elenco x a double escribir, cosas en double sqrt(double)devolver el valor a double y devuélvalo (este es el caso de x86-64 gcc 9.2 y x86-64 clang 9.0.0 en C Compiler Explorer.

El segundo caso puede ocurrir porque el compilador interpretó sqrt() como la función C sqrt()que sólo está definido para double. Si la función recién definida se llama repetidamente, esto puede causar una desventaja de rendimiento significativa. Lo que es peor, a veces incluso puede provocar resultados erróneos. Considere la siguiente función:

#include <cmath>

long double my_sqrt_3(long double x) {
    return sqrt(x);
}

Si sqrt() se interpreta como la C sqrt() función, en un chip de CPU que la admita long double tipo que es más preciso que doubleEs probable que esta función cause una pérdida de precisión cada vez que se llama e incluso puede producir resultados ridículos cuando x es lo suficientemente grande. En una CPU x86_64 reciente, usando gcc 8.3, el siguiente fragmento de código

#include <iostream>

int main() {
    std::cout << my_sqrt_3(1e310L) << ' ' << std::sqrt(1e310L) << std::endl;
    return 0;
}

salidas

inf 1e+155

¡La raíz cuadrada de un número finito es infinita! Esto es porque x se lanza implícitamente por primera vez para double en my_sqrt_3que no es lo suficientemente preciso como para almacenar un número tan grande como 1e310 y por lo tanto convertido en inf.

Conclusión: no utilice la «versión global» de las funciones estándar de C++; siempre usa eso en el std espacio de nombres.

Source link

Hi, I’m Corina Guzman

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *