问题来自示例代码https://en.cppreference.com/w/cpp/io/basic_istream/putback。
#include <sstream>
#include <iostream>
int main()
{
std::istringstream s2("Hello, world"); // input-only stream
s2.get();
if (s2.putback('Y')) // cannot modify input-only buffer
std::cout << s2.rdbuf() << '\n';
else
std::cout << "putback failed\n";
s2.clear();
if (s2.putback('H')) // non-modifying putback
std::cout << s2.rdbuf() << '\n';
else
std::cout << "putback failed\n";
}
为什么s2.putback('Y')
失败了却s2.putback('H')
成功了?后者不是修改输入流缓冲区的操作吗?
此外,在做一些实验时,我感到有些困惑。 与上面的示例相比,我添加了1行代码,第二个结果失败了。为什么?
#include <sstream>
#include <iostream>
int main()
{
std::istringstream s2("Hello, world"); // input-only stream
s2.get();
if (s2.putback('Y')) // cannot modify input-only buffer
std::cout << s2.rdbuf() << '\n';
else
std::cout << "putback failed\n";
std::cout << s2.rdbuf() << '\n'; //1 line code added
s2.clear();
if (s2.putback('H')) // non-modifying putback
std::cout << s2.rdbuf() << '\n';
else
std::cout << "putback failed\n";
}
答案 0 :(得分:4)
为什么
s2.putback('Y')
失败了却s2.putback('H')
成功了?后者不是修改输入流缓冲区的操作吗?
调用s2.putback('H')
可能修改缓冲区,但是在这种情况下,不会进行修改,因为数据已经以'H'
开头。
您可以举例说明这种行为:
s2.clear();
assert(s2.putback('H')); // Ok, replacing 'H' with 'H' doesn't change anything
assert(!s2.putback('Z')); // Can't modify.
答案 1 :(得分:3)
您可以进一步了解sputbackc
的行为。
如果在获取区域(
gptr() > eback()
)中有一个回退位置,并且字符c等于gptr()
左边的一个字符(由Traits::eq(c, gptr()[-1])
确定) ,然后只需递减下一个指针(gptr()
)。
因此,对于s2.putback('H')
,仅下一个指针递减。缓冲区未更改。
回答您的编辑:basic_ostream& operator<<( std::basic_streambuf<CharT, Traits>* sb);
提取由sb
维护的字符,因此在std::cout << s2.rdbuf() << '\n';
之后,下一个指针指向缓冲区的末尾,这导致s2.putback('H')
失败。