1

我在某处找到了这段代码。它以一种奇怪的方式将“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);
}
4

2 回答 2

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()是一个函数,它接受我们的 range 类的一个实例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);
}

效果是我们循环遍历缓冲区中的每个字符并将其复制到标准输出。

于 2013-08-24T20:39:49.577 回答
2
printbuf(&buf, std::cout);

std::stringbuf*作为第一个参数传递会导致X匹配的隐式构造printbuf()

而且对于第二个参数,会发生隐式构造,std::ostreambuf_iterator<char>std::cout(std::ostream)创建一个实例

void printbuf(X x, std::ostreambuf_iterator<char> it)
{
    for (auto c : x)
    {
        *it = c;
    }
}

在 printbuf 中,foreach 循环(基于范围的 for 循环)使用X::begin()andX::end()循环遍历包装中的所有字符,并通过( )std::stringbuf将它们写入std::coutstd::ostreambuf_iteratorit

于 2013-08-24T20:37:10.910 回答