Перегрузка << оператор и рекурсия
Я попробовал следующий код:
#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
В обоих случаях он компилируется, и в обоих случаях он вызывает переполнение стека.
Однако без "хе-хе" переполнение стека происходит немного раньше.