Why is #include <string> preventing a stack overflow error here?

c++, explicit, stack-overflow, string

Solution

Indeed, very interesting behavior.

Any idea why I get I runtime error when commenting out `#include <string>`

With MS VC++ compiler the error happens because if you do not `#include <string>` you won't have `operator<<` defined for `std::string`.

When the compiler tries to compile `ausgabe << f.getName();` it looks for an `operator<<` defined for `std::string`. Since it was not defined, the compiler looks for alternatives. There is an `operator<<` defined for `MyClass` and the compiler tries to use it, and to use it it has to convert `std::string` to `MyClass` and this is exactly what happens because `MyClass` has a non-explicit constructor! So, the compiler ends up creating a new instance of your `MyClass` and tries to stream it again to your output stream. This results in an endless recursion:

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

To avoid the error you need to `#include <string>` to make sure that there is an `operator<<` defined for `std::string`. Also you should make your `MyClass` constructor explicit to avoid this kind of unexpected conversion. Rule of wisdom: make constructors explicit if they take only one argument to avoid implicit conversion:

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

    const string& getName() const
    {
        return figName;
    }
};

It looks like `operator<<` for `std::string` gets defined only when `<string>` is included (with the MS compiler) and for that reason everything compiles, however you get somewhat unexpected behavior as `operator<<` is getting called recursively for `MyClass` instead of calling `operator<<` for `std::string`.

Does that mean that through `#include <iostream>` string is only included partly?

No, string is fully included, otherwise you wouldn't be able to use it.

Problem

This is my sample code: ``` #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; } ``` If I comment out `#include <string>` I don't get any compiler error, I guess because it's kind of included through `#include <iostream>`. If I "right-click --> Go to Definition" in Microsoft VS they both point to the same line in the `xstring` file: ``` typedef basic_string<char, char_traits<char>, allocator<char> > string; ``` But when I run my program, I get an exception error: 0x77846B6E (ntdll.dll) in OperatorString.exe: 0xC00000FD: Stack overflow (Parameter: 0x00000001, 0x01202FC4) Any idea why I get a runtime error when commenting out `#include <string>`? I'm using VS 2013 Express.

Original source

Related problems