【问题标题】:I can't understand the use of std::istream_iterator我无法理解 std::istream_iterator 的使用
【发布时间】:2020-12-26 13:49:27
【问题描述】:

我看不懂下面的代码。

(来自https://www.boost.org/doc/libs/1_74_0/more/getting_started/unix-variants.html

#include <boost/lambda/lambda.hpp>
#include <iostream>
#include <iterator>
#include <algorithm>

int main()
{
    using namespace boost::lambda;
    typedef std::istream_iterator<int> in;

    std::for_each(
        in(std::cin), in(), std::cout << (_1 * 3) << " " );
}

网页没有为代码解释任何内容。

我无法理解的是std::for_each函数的行。

std::for_each 定义如下。

template <class InputIterator, class Function>
Function for_each(InputIterator first, InputIterator last, Function fn);

所以firstin(std::cin)last 只是in()functioncout 语句。

谁能给我解释一下示例代码中firstlast的语法和含义?

first迭代器好像是用初始值std::cin构造的,但是最后一个值in()有什么用呢?

我也看不懂_1 部分。

程序输出3 *我输入的任意数量的整数值。

【问题讨论】:

  • 阅读istream_iterator 构造函数。还有一个类似的例子:en.cppreference.com/w/cpp/iterator/istream_iterator/…
  • in() 构造流尾迭代器
  • boost::lambda::_1 也是一个占位符,它创建一个需要一个参数的 lambda 函数。
  • 啊,谢谢(我正在阅读 cppreferece 页面并发现了这一点)。 @bakaDev 您可以将其发布为答案以便我选择吗?

标签: c++ boost iterator istream-iterator


【解决方案1】:

首先对std::for_each函数做一点解释。

该函数循环遍历一组迭代器,从头到尾,为范围内的每个元素调用一个函数。

如果你有例如整数向量:

std::vector<int> v = { 1, 2, 3, 4 };

并且想要打印打印它们,那么你可以这样做:

std::for_each(v.begin(), v.end(), [](int val) { std::cout << val; });

上面对std::for_each的调用相当于:

for (auto i = v.begin(); i != v.end(); ++i)
{
    std::cout << *i;
}

现在,如果我们在问题中使用std::istream_iterator,它会使用迭代器包装输入运算符&gt;&gt;

使用标准 C++ lambda 重写 std::for_each 调用,它看起来像这样:

std::for_each(in(std::cin), in(), [](int value) { std::cout << (value * 3) << " " ); });

如果我们把它翻译成“正常的”for 迭代器循环,那么它变成:

for (auto i = in(std::cin); i != in(); ++i)
{
    std::cout << (*i * 3) << " ";
}

它的作用是从std::cin 读取整数输入(直到文件结束或错误),然后输出乘以3 的值和一个空格。


如果您想知道in(std::cin)in(),您必须记住instd::istream_iterator&lt;int&gt; 类型的别名。

这意味着in(std::cin)std::istream_iterator&lt;int&gt;(std::cin) 相同。 IE。它创建一个std::istream_iterator&lt;int&gt; 对象,并将std::cin 传递给构造函数。而in() 构造了一个结束迭代器对象。

再清楚一点,代码相当于:

std::istream_iterator<int> the_beginning(std::cin);
std::istream_iterator<int> the_end;  // Default construct, becomes the "end" iterator

for (std::istream_iterator<int> i = the_beginning; i != the_end; ++i)
{
    int value = *i;  // Dereference iterator to get its value
                     // (effectively the same as std::cin >> value)

    std::cout << (value * 3) << " ";
}

【讨论】:

  • 感谢您的友好解释! (但我知道基本的迭代器用法,你错过了 _1 的解释,所以我选择了另一个答案。)
【解决方案2】:

谁能给我解释一下示例代码中firstlast的语法和含义?

first迭代器好像是用初始值std::cin构造的,但是最后一个值in()有什么用呢?

如果你看一下std::istream_iterator的构造函数的描述,你可以看到in()构造了end-of-stream迭代器。

istream_iterator(); //  < C++11
constexpr istream_iterator(); // > C++11

构造流结束迭代器,对存储的值进行值初始化。如果定义 auto x = T(); 中的初始化程序是常量初始化程序(C++11 起),则此构造函数为 constexpr

至于in(std::cin)

istream_iterator( istream_type& stream );
istream_iterator( const istream_iterator& other );  //< C++11
istream_iterator( const istream_iterator& other ) = default; // > C++11

初始化迭代器,将流的地址存储在数据成员中,并从输入流中执行第一次读取以初始化缓存值数据成员。

source

我也看不懂_1部分

这样做是用迭代序列中的每个元素替换 占位符 _1 并将其乘以 3,使用输出流中的结果,因为它应该使用一元函数论据。

for_each(a.begin(), a.end(), std::cout << _1 << ' ');

表达式std::cout &lt;&lt; _1 &lt;&lt; ' ' 定义了一个一元函数对象。变量_1 是该函数的参数,是实际参数的占位符。在for_each 的每次迭代中,都会使用a 的元素作为实际参数调用该函数。这个实际参数被替换为占位符,并评估函数的“主体”。

source

【讨论】:

  • @ChanKim,不客气,是的,你是对的,它是 boost::lambda::placeholder1_type &amp;boost::lambda::&lt;unnamed&gt;::_1 ,但基本上是一样的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-30
  • 2016-12-05
  • 1970-01-01
  • 2016-06-24
  • 1970-01-01
  • 2019-11-04
相关资源
最近更新 更多