vectors redimensionar metodo clase c++ std reserved

c++ - redimensionar - std:: vector methods



¿Puede una declaración afectar el espacio de nombres estándar? (2)

#include <iostream> #include <cmath> /* Intentionally incorrect abs() which seems to override std::abs() */ int abs(int a) { return a > 0? -a : a; } int main() { int a = abs(-5); int b = std::abs(-5); std::cout<< a << std::endl << b << std::endl; return 0; }

Esperaba que la salida fuera -5 y 5 , pero la salida fuera -5 y -5 .

Me pregunto por qué va a pasar este caso.

¿Tiene algo que ver con el uso de std o qué?


La especificación del lenguaje allows implementaciones implementen <cmath> declarando (y definiendo) las funciones estándar en el espacio de nombres global y luego llevándolas al espacio de nombres std por medio de declaraciones de uso. No se especifica si este enfoque se utiliza

20.5.1.2 Encabezados
4 [...] En la biblioteca estándar de C ++, sin embargo, las declaraciones (excepto los nombres que se definen como macros en C) están dentro del alcance del espacio de nombres (6.3.6) del espacio de nombres std . No se especifica si estos nombres (incluidas las sobrecargas agregadas en las Cláusulas 21 a 33 y el Anexo D) se declaran primero dentro del alcance del espacio de nombres global y luego se inyectan en el espacio de nombres std mediante declaraciones de uso explícitas (10.3.3).

Aparentemente, está tratando con una de las implementaciones que decidió seguir este enfoque (por ejemplo, GCC). Es decir, su implementación proporciona ::abs , mientras que std::abs simplemente "se refiere" a ::abs .

Una pregunta que queda en este caso es por qué, además del estándar ::abs , pudo declarar su propio ::abs , es decir, por qué no hay un error de definición múltiple. Esto puede deberse a otra característica proporcionada por algunas implementaciones (por ejemplo, GCC): declaran funciones estándar como los denominados símbolos débiles , lo que le permite "reemplazarlos" con sus propias definiciones.

Estos dos factores juntos crean el efecto que usted observa: el reemplazo con símbolo débil de ::abs también resulta en el reemplazo de std::abs . En qué medida está de acuerdo con el estándar de idioma es una historia diferente ... En cualquier caso, no confíe en este comportamiento, ya que no está garantizado por el idioma.

En GCC, este comportamiento se puede reproducir mediante el siguiente ejemplo minimalista. Un archivo fuente

#include <iostream> void foo() __attribute__((weak)); void foo() { std::cout << "Hello!" << std::endl; }

Otro archivo fuente

#include <iostream> void foo(); namespace N { using ::foo; } void foo() { std::cout << "Goodbye!" << std::endl; } int main() { foo(); N::foo(); }

En este caso, también observará que la nueva definición de ::foo ( "Goodbye!" ) En el segundo archivo de origen también afecta el comportamiento de N::foo . Ambas llamadas emitirán "Goodbye!" . Y si elimina la definición de ::foo del segundo archivo de origen, ambas llamadas se enviarán a la definición "original" de ::foo y la salida "Hello!" .

El permiso dado por el anterior 20.5.1.2/4 está ahí para simplificar la implementación de <cmath> . Las implementaciones pueden incluir simplemente el estilo C <math.h> , luego volver a declarar las funciones en std y agregar algunas adiciones y ajustes específicos de C ++. Si la explicación anterior describe adecuadamente la mecánica interna del problema, entonces una parte importante depende de la capacidad de reemplazo de los símbolos débiles para las versiones de estilo C de las funciones.

Tenga en cuenta que si simplemente reemplazamos globalmente el int con el double en el programa anterior, el código (bajo GCC) se comportará "como se esperaba" - generará -5 5 . Esto sucede porque la biblioteca estándar de C no tiene función abs(double) . Al declarar nuestros propios abs(double) , no reemplazamos nada.

Pero si después de cambiar de int con double también cambiamos de abs a fabs , el comportamiento extraño original reaparecerá en toda su gloria (salida -5 -5 ).

Esto es consistente con la explicación anterior.


Tu código provoca un comportamiento indefinido.

C ++ 17 [extern.names] / 4:

Cada firma de función de la biblioteca estándar de C declarada con enlace externo se reserva a la implementación para su uso como una firma de función con enlace externo "C" y externo "C ++", o como un nombre de ámbito de espacio de nombres en el espacio de nombres global.

Por lo tanto, no puede crear una función con el mismo prototipo que la función de biblioteca de C estándar int abs(int); . Independientemente de los encabezados que realmente incluya o si esos encabezados también colocan los nombres de la biblioteca C en el espacio de nombres global.

Sin embargo, se podría sobrecargar los abs si proporciona diferentes tipos de parámetros.