tipo stackoverflowexception significa que excepción español error controlada c++ string stack-overflow explicit

c++ - significa - system.stackoverflowexception c#



¿Por qué#include<string> evita un error de desbordamiento de pila aquí? (2)

De hecho, comportamiento muy interesante.

Alguna idea de por qué me aparece un error de tiempo de ejecución al comentar #include <string>

Con el compilador MS VC ++, el error ocurre porque si no #include <string> no tendrá el operator<< definido para std::string .

Cuando el compilador intenta compilar ausgabe << f.getName(); busca un operator<< definido para std::string . Como no se definió, el compilador busca alternativas. Hay un operator<< definido para MyClass y el compilador intenta usarlo, y para usarlo tiene que convertir std::string a MyClass y esto es exactamente lo que sucede porque ¡ MyClass tiene un constructor no explícito! Entonces, el compilador termina creando una nueva instancia de su MyClass e intenta transmitirlo nuevamente a su flujo de salida. Esto resulta en una recursión sin fin:

start: operator<<(MyClass) -> MyClass::MyClass(MyClass::getName()) -> operator<<(MyClass) -> ... goto start;

Para evitar el error, debe #include <string> para asegurarse de que haya un operator<< definido para std::string . También debe hacer explícito su constructor MyClass para evitar este tipo de conversión inesperada. Regla de sabiduría: haga explícitos a los constructores si toman solo un argumento para evitar la conversión implícita:

class MyClass { string figName; public: explicit MyClass(const string& s) // <<-- avoid implicit conversion { figName = s; } const string& getName() const { return figName; } };

Parece que el operator<< para std::string se define solo cuando se incluye <string> (con el compilador de MS) y por esa razón todo se compila, sin embargo, se obtiene un comportamiento inesperado ya que el operator<< se llama recursivamente para MyClass de llamar al operator<< para std::string .

¿ #include <iostream> significa que a través de la cadena #include <iostream> solo se incluye parcialmente?

No, la cadena está completamente incluida, de lo contrario no podría usarla.

Este es mi código de muestra:

#include <iostream> #include <string> using namespace std; class MyClass { string figName; public: MyClass(const string& s) { figName = s; } const string& getName() const { return figName; } }; ostream& operator<<(ostream& ausgabe, const MyClass& f) { ausgabe << f.getName(); return ausgabe; } int main() { MyClass f1("Hello"); cout << f1; return 0; }

Si comento #include <string> no obtengo ningún error del compilador, supongo que se incluye a través de #include <iostream> . Si hago "clic derecho -> Ir a definición" en Microsoft VS, ambos apuntan a la misma línea en el archivo xstring :

typedef basic_string<char, char_traits<char>, allocator<char> > string;

Pero cuando ejecuto mi programa, aparece un error de excepción:

0x77846B6E (ntdll.dll) en OperatorString.exe: 0xC00000FD: Desbordamiento de pila (Parámetro: 0x00000001, 0x01202FC4)

¿Alguna idea de por qué aparece un error de tiempo de ejecución al comentar #include <string> ? Estoy usando VS 2013 Express.


El problema es que su código está haciendo una recursión infinita. El operador de transmisión para std::string ( std::ostream& operator<<(std::ostream&, const std::string&) ) se declara en el archivo de encabezado <string> , aunque std::string se declara en otro archivo de encabezado (incluido por <iostream> y <string> ).

Cuando no incluye <string> el compilador intenta encontrar una manera de compilar ausgabe << f.getName(); .

Sucede que ha definido tanto un operador de transmisión para MyClass como un constructor que admite una std::string , por lo que el compilador la usa (a través de la construcción implícita ), creando una llamada recursiva.

Si declara explicit su constructor ( explicit MyClass(const std::string& s) ), su código ya no se compilará, ya que no hay forma de llamar al operador de transmisión con std::string , y se verá obligado a incluye el encabezado <string> .

EDITAR

Mi entorno de prueba es VS 2010, y comenzando en el nivel de advertencia 1 ( /W1 ) le advierte sobre el problema:

advertencia C4717: ''operador <<'': recursivo en todas las rutas de control, la función provocará un desbordamiento de la pila en tiempo de ejecución