Перегрузка << оператор и рекурсия

Я попробовал следующий код:

#include <iostream>
using std::cout;
using std::ostream;

class X
{
public:
    friend ostream& operator<<(ostream &os, const X& obj) 
    {
        cout << "hehe";          // comment this and infinite loop is gone
        return (os << obj);
    }
};

int main()
{
    X x;
    cout << x;
    return 0;
}

Когда я компилирую и запускаю это, это как и ожидалось; бесконечный цикл. Если я удалю cout оператор внутри функции друга, рекурсия не происходит. Почему это так?

2 ответа

Решение

Оптимизатор решает, что все ваши оставшиеся действия не имеют никакого эффекта, и оптимизирует их. Правильно это или нет - другое дело.

Особенно:

X x;

создает пустой объект "х"

cout << x;

звонки:

return (os << obj);

который добавляет пустой объект; компилятор замечает, что 'os' не вырос с момента последнего вызова и не обещает делать это дальше (и больше ничего не происходит), поэтому он решает, что весь бизнес является избыточным и может быть усечен на этом этапе.

В случае, если вы звоните

    cout << "hehe";          // comment this and infinite loop is gone

есть некоторые дополнительные действия, поэтому оптимизатор не удаляет следующий вызов.

Я думаю, если вы инициализировали x с чем-нибудь непустым, или выполнил любое ненулевое действие, кроме cout << "hehe";, у вас будет такая же рекурсия.

В обоих случаях (с надписью "хе-хе" и без нее) Visual Studio 2005 выдает следующее предупреждение:

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

В обоих случаях он компилируется, и в обоих случаях он вызывает переполнение стека.

Однако без "хе-хе" переполнение стека происходит немного раньше.

Другие вопросы по тегам