Рассмотрим следующий код:
class C{};
std::ostream &operator <<(std::ostream &o, const C &) {
o.fill('!');
o.width(8);
return o << 42;
}
int main() {
std::cout << C{} << '\n';
std::cout << 42 << '\n';
return 0;
}
Это выводит:
!!!!!!42
42
я ожидал !!!!!!42
дважды, потому что я изменил состояние предоставленного std::ostream o
призвание fill
а также width
внутри operator <<
, поэтому я привык думать, что символ заполнения и ширина, заданная в операторе, будут утечка вне вызова оператора, как если бы они были липкими свойствами.
Как видите, я не сбрасываю поток и не устанавливаю заново символ заполнения или ширину, так почему (и как) сохраняется исходное поведение?
Таким образом, вопрос: как свойства ostream
возвращаются в предыдущее состояние после вызова моего operator<<
за class C
?
Это не беспокоит меня, я доволен этим поведением, но я хочу понять, как это работает.
Как подчеркивал underscore_d: width
не липкий Но на самом деле такого атрибута нет stickiness
для классов iostream и их манипуляторов.
Хотя, если бы ширина не была сброшена предыдущей <<
вызов оператора, ширина также будет влиять на вывод \n
:
std::cout << std::setw(10) << std::setfill('!') << 42 << '\n';
std::cout << std::setw(10) << std::setfill('!') << 42 << std::setw(10) << '\n';
дает
!!!!!!!!42
!!!!!!!!42!!!!!!!!!
.