我在某个地方找到了这个代码。它以“奇怪的方式”将“abcd”打印到屏幕上。我希望有人告诉我它是如何运作的:
#include <iostream>
#include <sstream>
class X
{
typedef std::istreambuf_iterator<char> Iter;
Iter it;
public:
X(std::streambuf* p) : it(p) { }
Iter begin()
{ return it; }
Iter end()
{ return Iter(); }
};
void printbuf(X x, std::ostreambuf_iterator<char> it)
{
for (auto c : x)
{
*it = c;
}
}
int main()
{
std::stringbuf buf("abcd", std::ios_base::in | std::ios_base::out);
printbuf(&buf, std::cout);
}
答案 0 :(得分:4)
我们有一个X
类,它封装了istreambuf_iterator<char>
。这是一个迭代器类型,它允许我们将流缓冲区视为标准算法的迭代器范围。
class X
{
typedef std::istreambuf_iterator<char> Iter;
Iter it;
public:
该类可以从指向流缓冲区实例的指针构建。
X(std::streambuf* p) : it(p) { }
它公开begin()
和end()
成员函数,以允许它与基于范围的for
循环一起使用。
Iter begin()
{ return it; }
Iter end()
{ return Iter(); }
};
printbuf()
是一个函数,它接受我们的范围类X
的实例,以及ostreambuf_iterator<char>
,你猜对了它 - 允许我们使用输出流缓冲区作为输出迭代器。
void printbuf(X x, std::ostreambuf_iterator<char> it)
{
所以我们遍历输入范围中的每个字符。
for (auto c : x)
{
如果之前没有处理输出迭代器,可以将它们视为类似指针的对象,使用取消引用和赋值来写值。 back_insert_iterator
是一个常用的输出迭代器,用于构建容器 - 通常使用back_inserter
构造容器。但我离题了。
我们将每个字符复制到输出迭代器。
*it = c;
}
}
int main()
{
这里我们构造一个字符串缓冲区,它既是输入和输出流缓冲区。我们在此示例中仅使用输入功能。
std::stringbuf buf("abcd", std::ios_base::in | std::ios_base::out);
现在我们使用隐式构造的X
实例将字符串缓冲区视为迭代器范围。然后我们将该范围复制到输出流缓冲区迭代器 - 也隐式构造 - 到std::cout
。
printbuf(&buf, std::cout);
}
结果是我们循环遍历缓冲区中的每个字符并将其复制到标准输出。
答案 1 :(得分:2)
printbuf(&buf, std::cout);
将std::stringbuf*
作为第一个参数传递导致隐式构建X
以匹配printbuf()
还有第二个参数,一个隐含的
发生构造,从std::ostreambuf_iterator<char>
(std :: ostream)创建std::cout
的实例
void printbuf(X x, std::ostreambuf_iterator<char> it)
{
for (auto c : x)
{
*it = c;
}
}
在printbuf中,foreach循环(基于循环的范围)使用X::begin()
和X::end()
循环包裹std::stringbuf
中的所有字符,并通过std::cout
将它们写入std::ostreambuf_iterator
it
({{1}})