5

我有这个简短的代码片段。我不明白这个结构是什么意思。我知道这段代码从输入中读取数字并在 unordered_map 中计算其频率。但什么是[&]?是什么意思(int x)?代表什么input(cin)?我的意思是括号中的“cin”?for_each 如何迭代input(cin)到空的 eof 参数?我不明白这整个结构。

unordered_map<int,int> frequency;
istream_iterator<int> input(cin);
istream_iterator<int> eof;

for_each(input, eof, [&] (int x)
    { frequency[x]++; });
4

3 回答 3

6

istream_iteratoristream允许您从传递给构造函数的 中迭代地提取项目。eof对象是这样解释的:

此迭代器存在一个特殊值:流结束;当迭代器设置为此值时,要么已到达流的末尾(应用于流的运算符 void* 返回 false),要么已使用其默认构造函数构造(未将其与任何 basic_istream 对象关联)。

for_each是一个循环构造,它采用迭代器#1 并递增它直到它与迭代器#2 相等。在这里,它采用包装标准输入的迭代器cin并将其递增(转换为提取项目),直到没有更多输入要消耗——这使得input比较等于eof并且循环结束。

该构造[&] (int x) { frequency[x]++; }是一个匿名函数;它只是内联编写函数的一种简写方式。可以达到大致相同的效果

unordered_map<int,int> frequency; // this NEEDS to be global now
istream_iterator<int> input(cin);
istream_iterator<int> eof;

void consume(int x) {
    frequency[x]++;
}

for_each(input, eof, consume);

简而言之:这段代码从标准输入中读取整数,直到所有可用数据都被消耗完,同时记录每个整数在地图中出现的频率。

于 2012-09-26T08:47:49.373 回答
2

你的问题有两个部分。

  1. 第一个涉及流迭代器。Anstd::istream_iterator<T>是由 some 构造的std::istream & s,并且在取消引用时,它的行为类似于{ T x; s >> x; return x; }。一旦提取失败,迭代器就等于默认构造的迭代器,用作“结束”迭代器。

    流迭代器允许您将流视为令牌的容器。例如:

    std::vector<int> v(std::istream_iterator<int>(std::cin),
                       std::istream_iterator<int>());
    
    std::copy(v.begin(), v.end(), std::ostream_iterator<int>(std::cout, " "));
    
  2. C++11 引入了lambda 表达式,它定义了匿名函数或函子(称为闭包)。一个简单的看起来像这样:

    auto f = [](int a, int b) -> double { return double(a) / double(b); };
    
    auto q = f(1, 2);  // q == 0.5
    

    f可以写成普通的自由函数,但自由函数必须出现在命名空间范围内或作为本地类的静态成员函数。(实际上这就是 lambda 表达式的类型!)请注意,lambda 表达式的类型是不可知的,只能通过 newauto关键字捕获。

    当 Lambda 充当可以捕获环境状态的复杂函数对象时,它们会变得更加有用。你的例子可能是这样写的:

    auto f = [&frequency](int x) -> void { ++frequency[x]; };
    

    捕获出现在第一个方括号之间的变量。此 lambda 等效于以下本地类和对象:

    struct F
    {
        F(std::unordered_map<int, int> & m) : m_(m) { }
        void operator()(int x) { ++m_[x]; }
    private:
        std::unordered_map<int, int> & m_;
    } f;
    

没有&在捕获列表中的变量是按值捕获的,即在闭包对象中创建一个副本。作为简写,您可以按值或按引用分别表示[=][&]捕获所有内容。

于 2012-09-26T09:03:27.313 回答
1

这是 STL std::for_each (non-C++11) 迭代输入直到等于eof[&] (int x) { frequency[x]++; }为每个值调用 lambda

因此,此代码计算 istream 中字符的频率;将它们保存到地图中

于 2012-09-26T08:46:52.993 回答