Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

People also ask

Why is the sky blue short answer?

The Short Answer: Sunlight reaches Earth's atmosphere and is scattered in all directions by all the gases and particles in the air. Blue light is scattered more than the other colors because it travels as shorter, smaller waves. This is why we see a blue sky most of the time.

What is the real colour of sky?

The sunlight reaching our eyes has a high ratio of short, bluish wavelengths compared to medium and long wavelengths, so we perceive the sky as being blue. Without an atmosphere the sky appears black, as evidenced by the lunar sky in pictures taken from the moon. But even a black sky has some lightness.

Why is the skyblue?

Gases and particles in Earth's atmosphere scatter sunlight in all directions. Blue light is scattered more than other colors because it travels as shorter, smaller waves. This is why we see a blue sky most of the time.

How is the sky blue but space is black?

Since there is virtually nothing in space to scatter or re-radiate the light to our eye, we see no part of the light and the sky appears to be black.


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.


The problem is that your code is doing an infinite recursion. The streaming operator for std::string (std::ostream& operator<<(std::ostream&, const std::string&)) is declared in <string> header file, although std::string itself is declared in other header file (included by both <iostream> and <string>).

When you don't include <string> the compiler tries to find a way to compile ausgabe << f.getName();.

It happens that you have defined both a streaming operator for MyClass and a constructor that admits a std::string, so the compiler uses it (through implicit construction), creating a recursive call.

If you declare explicit your constructor (explicit MyClass(const std::string& s)) then your code won't compile anymore, since there is no way to call the streaming operator with std::string, and you'll be forced to include the <string> header.

EDIT

My test environment is VS 2010, and starting at warning level 1 (/W1) it warns you about the problem:

warning C4717: 'operator<<' : recursive on all control paths, function will cause runtime stack overflow