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 de compilación, supongo que se incluye de alguna manera #include <iostream>. Si hago "clic derecho -> Ir a definición" en Microsoft VS, ambos apuntan a la misma línea en el xstringarchivo:
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.
c++
string
stack-overflow
explicit
aerotransportado
fuente
fuente

#include<iostream>y<string>ambos podrían incluir<common/stringimpl.h>....\main.cpp(23) : warning C4717: 'operator<<': recursive on all control paths, function will cause runtime stack overflowal ejecutar esta líneacl /EHsc main.cpp /Fetest.exeRespuestas:
De hecho, comportamiento muy interesante.
Con el compilador MS VC ++, el error ocurre porque si no lo hace, no
#include <string>lo habráoperator<<definidostd::string.Cuando el compilador intenta compilar
ausgabe << f.getName();busca unoperator<<definido parastd::string. Como no se definió, el compilador busca alternativas. Hay unoperator<<definida porMyClassy los intentos del compilador para usarlo, y para utilizarlo se tiene que convertirstd::stringaMyClassy esto es exactamente lo que sucede porqueMyClasstiene un constructor no explícito! Entonces, el compilador termina creando una nueva instancia de tuMyClasse intenta transmitirlo nuevamente a tu flujo de salida. Esto resulta en una recursión sin fin:Para evitar el error necesitas
#include <string>asegurarse de que haya unoperator<<definido parastd::string. También debe hacer que suMyClassconstructor sea explícito 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:Parece que
operator<<para lastd::stringobtiene sólo cuando se define<string>se incluye (con el compilador MS) y para que compila razón, todo, sin embargo, se obtiene un comportamiento algo inesperado ya queoperator<<se llama de forma recursiva para conseguirMyClassen lugar de llamaroperator<<astd::string.No, la cadena está completamente incluida, de lo contrario no podría usarla.
fuente
std::stringsin#include<string>todo tipo de cosas, puede ocurrir, no limitado a un error de tiempo de compilación. Llamar a la función u operador incorrecto es aparentemente otra opción.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<string>archivo de encabezado, aunquestd::stringsí se declara en otro archivo de encabezado (incluido por ambos<iostream>y<string>).Cuando no incluye
<string>el compilador intenta encontrar una manera de compilarausgabe << f.getName();.Sucede que ha definido tanto un operador de transmisión
MyClasscomo un constructor que admite astd::string, por lo que el compilador lo usa (a través de la construcción implícita ), creando una llamada recursiva.Si declara
explicitsu 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ónstd::stringy se verá obligado a incluir el<string>encabezado.EDITAR
Mi entorno de prueba es VS 2010, y comenzando en el nivel de advertencia 1 (
/W1) le advierte sobre el problema:fuente