理解std :: transform的行为有困难

时间:2013-06-26 13:38:17

标签: c++ std

考虑一下 -

#include <iostream>
#include <algorithm>
#include <functional>
#include <iterator>
#include <list>

int main()
{
  typedef std::list<int> L;
  L l(5);
  typedef L::const_iterator CI;
  typedef L::iterator I;
  CI cb = l.begin(), ce = l.end();
  I b = l.begin();
  std::transform(cb, --ce, ++b, std::bind2nd(std::plus<CI::value_type>(), 1));
  std::copy(l.begin(), l.end(), std::ostream_iterator<CI::value_type>(std::cout\
));
  std::cout<<std::endl;
  return 0;
}

根据我的说法,它的输出应该是01111,因为变换将从第一个迭代到第二个“倒数第二个”元素列表添加1到每个元素,并从“第二个”到“最后”元素覆盖。

但令我惊讶的是输出是01234

我错过了什么?我阅读了关于cppreference的转换文档

2 个答案:

答案 0 :(得分:3)

这是因为您将每个单独转换的结果存储到容器的下一个元素中,因此转换函数的下一个输入将是前一个转换的输出(因为你如何定义输入和输出范围)。

换句话说,transform()算法将处理容器的第一个元素(0),向其添加1,并存储结果(1)作为同一容器的第二个元素 。然后,它将处理第二个元素,现在是1;它会向其添加1,并将结果(2)存储为容器的第三个元素。依此类推,直到你进入最后一次迭代。

如果要获取输出01111,则应将转换结果存储到 diffferent 容器(live example)中:

std::vector<int> out(l.size());
std::transform(cb, --ce, ++out.begin(), 
//                       ^^^^^^^^^^^^^
    std::bind2nd(std::plus<CI::value_type>(), 1));

或使用不同的迭代策略as suggested by DyP in the commentslive example):

 std::transform(++cb, ce, ++b, std::bind2nd(std::plus<CI::value_type>(), 1));

答案 1 :(得分:3)

由于您开始在++b处将元素添加到同一容器中,因此会有一个偏移,这意味着您将元素i1插入到位置{{ 1}}。因此,当你移动时,你正在积累总和。假设变换按顺序处理元素,这就是前三次迭代将要执行的操作:

  

0 0 0 0 0

将1添加到位置0,将其置于位置1

  

0 1 0 0 0

将1添加到位置1,将其置于位置2

  

0 1 2 0 0

将1添加到位置2,将其置于位置3

  

0 1 2 3 0