对于C 11,STL现在具有std :: iota功能(参见reference).与std :: fill_n,std :: generate_n相比,没有std :: iota_n.什么是一个很好的实现呢?直接循环(替代1)或使用简单的lambda表达式(替代2)委托std :: generate_n?
备选方案1)
template<class OutputIterator, class Size, class T>
OutputIterator iota_n(OutputIterator first, Size n, T value)
{
while (n--)
*first++ = value++;
return first;
}
备选方案2)
template<class OutputIterator, class Size, class T>
OutputIterator iota_n(OutputIterator first, Size n, T value)
{
return std::generate_n(first, n, [&](){ return value++; });
}
这两种方案都会产生优化编译器的等效代码吗?
更新:结合了@Marc Mutz的优点,也在目标点返回迭代器.这也是在C 11中与C 98相比std::generate_n
更新的方式.
解决方法:
作为一个随机的例子,我使用g -S -O2 -masm = intel(GCC 4.7.1,x86_32)编译了以下代码:
void fill_it_up(int n, int * p, int val)
{
asm volatile("DEBUG1");
iota_n(p, n, val);
asm volatile("DEBUG2");
iota_m(p, n, val);
asm volatile("DEBUG3");
for (int i = 0; i != n; ++i) { *p++ = val++; }
asm volatile("DEBUG4");
}
这里iota_n是第一个版本,iota_m是第二个版本.这三个案例中的程序集如下:
test edi, edi
jle .L4
mov edx, eax
neg edx
lea ebx, [esi+edx*4]
mov edx, eax
lea ebp, [edi+eax]
.p2align 4,,7
.p2align 3
.L9:
lea ecx, [edx+1]
cmp ecx, ebp
mov DWORD PTR [ebx-4+ecx*4], edx
mov edx, ecx
jne .L9
使用-O3时,这三个版本也非常相似,但更长(使用条件移动和punpcklqdq等).