有人可以帮助解释这行代码是如何工作的吗? 我不明白运算符在transform()中是如何工作的。 谢谢!
typedef std::list<int> L;
L l(5);
typedef L::const_iterator CI;
CI cb = l.begin(), ce = l.end();
typedef L::iterator I;
I b = l.begin();
std::transform(cb, --ce, ++b, [] (CI::value_type n) { return ++n; });
std::copy(l.begin(), l.end(), std::ostream_iterator<CI::value_type>(std::cout));
答案 0 :(得分:1)
该行
std::transform(cb, --ce, ++b, [] (CI::value_type n) { return ++n; });
表示:
递减ce
,递增b
对于从cb
开始到ce
结束的每个值(非包含!),请从b
开始放置一个递增的值。
答案 1 :(得分:1)
绘制图片可能会有所帮助。这一行:
std::transform(cb, --ce, ++b, [] (CI::value_type n) { return ++n; });
可以改写为:
--ce;
++b;
std::transform(cb, ce, b, [] (CI::value_type n) { return ++n; });
其中:
0 --> 0 --> 0 --> 0 --> 0 --> {null}
↑ ↑ ↑
cb b ce
循环的每一步都将*b
设置为f(*cb) == *cb + 1
,并递增两个迭代器。因此,经过一步之后我们就会:
0 --> 1 --> 0 --> 0 --> 0 --> {null}
↑ ↑ ↑
cb b ce
第二次之后:
0 --> 1 --> 2 --> 0 --> 0 --> {null}
↑ ↑ ↑
cb b ce
等
答案 2 :(得分:1)
该列表有5个由零初始化的元素:
L l(5);
你可以想象他们喜欢
{ 0, 0, 0, 0, 0 }
迭代器对cb, - em设置列表的以下元素范围
{ 0, 0, 0, 0, 0 }
^ ^
|__________|
cb --ce
由于ce:--ce
的减少,列表的最后一个元素未包含在列表中。
这是第一个迭代器指向列表的第一个元素,第二个迭代器指向列表的最后一个元素。
Iterator ++ b设置范围的开头
++b
| |
{ 0, 0, 0, 0, 0 }
^ ^
|__________|
cb --ce
该算法以下列方式工作。在第一次迭代中,cb指向的值增加并存储在iterator ++ b指向的元素中
++b
| |
{ 0, 1, 0, 0, 0 }
^ ^
|__________|
cb --ce
然后迭代器向右移动。
++b
| |
{ 0, 1, 0, 0, 0 }
^ ^
|_______|
cb --ce
然后重复该操作:迭代器cb指向的元素中的值增加并存储在iterator ++ b指向的元素中,你得到
++b
| |
{ 0, 1, 2, 0, 0 }
^ ^
|_______|
cb --ce
然后迭代器再次向右移动
++b
| |
{ 0, 1, 2, 0, 0 }
^ ^
|____|
cb --ce
等等。
使用标头std::iota
中声明的标准算法<numeric>
可以更简单明了地完成此操作。例如
#include <numeric>
//...
std::iota( l.begin(), l.end(), 0 );
这是一个展示两种方法的示范程序
#include <iostream>
#include <algorithm>
#include <numeric>
#include <list>
#include <iterator>
int main()
{
std::list<int> l( 5 );
for ( int x : l ) std::cout << x << ' ';
std::cout << std::endl;
std::transform( l.begin(), std::prev( l.end() ), std::next( l.begin() ),
[]( int x ) { return ++x; } );
for ( int x : l ) std::cout << x << ' ';
std::cout << std::endl;
std::cout << std::endl;
l.assign( 5, 0 );
for ( int x : l ) std::cout << x << ' ';
std::cout << std::endl;
std::iota( l.begin(), l.end(), 0 );
for ( int x : l ) std::cout << x << ' ';
std::cout << std::endl;
return 0;
}
程序输出
0 0 0 0 0
0 1 2 3 4
0 0 0 0 0
0 1 2 3 4
如果您的编译器支持C ++ 2014,那么您也可以采用以下方式:)
l.assign( 5, 0 );
for ( int x : l ) std::cout << x << ' ';
std::cout << std::endl;
std::generate( l.begin(), l.end(), [value = 0]() mutable { return value++; } );
for ( int x : l ) std::cout << x << ' ';
std::cout << std::endl;
输出与上面相同。
答案 3 :(得分:1)
论点nr。 4是lambda expression,您可以选择拥有自己的变换函数。这个:[] (CI::value_type n) { return ++n; }
的作用是:
由于它是一元操作,你可以有一个参数,上面的lambda有一个参数。 (transform
允许您也通过两个参数进行二进制运算)
函数transform
为cb to --ce
范围内的每个元素调用上面的lambda。
CI::value_type n
是int
,因此transform会调用传递int的函数,并在返回之前递增它,将结果存储在从++b
开始的范围内。
例如,使用函数代替使用lambda也可以工作:
int inc(int n)
{
return ++n;
}
std::transform(cb, --ce, ++b, inc);
此外,对我来说这样做更有意义:
std::transform(cb, ce, b, [](CI::value_type n){ return ++n; });
遍历范围中的每个值,递增值。 这是DEMO