在C ++ 11中,STL现在具有一个std::iota功能(请参阅参考资料)。与相比std::fill_n,std::generate_n没有std::iota_n。有什么好的实现方法?直接循环(替代1)或std::generate_n使用简单的lambda表达式委派(替代2)?
std::iota
std::fill_n
std::generate_n
std::iota_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的优点,也可以在目标点返回迭代器。std::generate_n与C 98相比,这也是C 11中的更新方式。
作为一个随机示例,我使用g++ -S -O2 -masm=intel(GCC 4.7.1,x86_32)编译了以下代码:
g++ -S -O2 -masm=intel
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第二个版本。在所有三种情况下,程序集都是这样的:
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与此类似的)。
-O3
punpcklqdq