C++11 initializer_list 和 Range-based for loop 学习理解
win10 + vs2017
源码如下:
int main()
{
vector< int > numbers = { 1, 2, 3, 4, 5 };
for (auto num : numbers)
{
printf( "num = %d\n", num );
}
return 0;
}
汇编理解如下:
int main()
{
# 入栈
00933f63 sub esp,150h
00933f69 push ebx
00933f6a push esi
00933f6b push edi
00933f6c lea edi,[ebp-150h]
00933f72 mov ecx,54h
00933f77 mov eax,0cccccccch
00933f7c rep stos dword ptr es:[edi]
00933f7e mov eax,dword ptr [__security_cookie (093e004h)]
00933f83 xor eax,ebp
00933f85 mov dword ptr [ebp-4],eax
vector< int > numbers = { 1, 2, 3, 4, 5 };
// memset( &numbers, 0x00, sizeof ( numbers ) );
// sizeof ( numbers ) == 10h
00933f88 push 10h
00933f8a lea ecx,[numbers]
00933f8d call std::vector<int,std::allocator<int> >::__autoclassinit2 (09314abh)
// [ebp-14ch, ebp-138h) 这段内存是5个整形(20个字节),分别赋值为1,2,3,4,5
00933f92 mov dword ptr [ebp-14ch],1
00933f9c mov dword ptr [ebp-148h],2
00933fa6 mov dword ptr [ebp-144h],3
00933fb0 mov dword ptr [ebp-140h],4
00933fba mov dword ptr [ebp-13ch],5
// 创建allocator对象,供后面vector构造使用,地址为 ebp-111h
00933fc4 lea ecx,[ebp-111h]
00933fca call std::allocator<int>::allocator<int> (0931163h)
00933fcf push eax
// std::initializer_list<int> 构造
// initializer_list(const _elem *_first_arg, const _elem *_last_arg)
00933fd0 lea eax,[ebp-138h]
00933fd6 push eax
00933fd7 lea ecx,[ebp-14ch]
00933fdd push ecx
00933fde lea ecx,[ebp-124h]
00933fe4 call std::initializer_list<int>::initializer_list<int> (09314a6h)
// vector 构造
// vector(initializer_list<_ty> _ilist, const _alloc& _al = _alloc())
// _al参数是在 00933fcf 位置压栈的
// _ilist参数是按值传递,将成员_first和_last分两次压栈,对应下面4行
00933fe9 mov edx,dword ptr [eax+4]
00933fec push edx
00933fed mov eax,dword ptr [eax]
00933fef push eax
00933ff0 lea ecx,[numbers]
00933ff3 call std::vector<int,std::allocator<int> >::vector<int,std::allocator<int> > (0931168h)
for (auto num : numbers)
// std::vector<int,std::allocator<int> >::begin() 结果保存在 dword ptr [ebp-30h]
00933ff8 lea eax,[numbers]
00933ffb mov dword ptr [ebp-24h],eax
00933ffe mov ecx,dword ptr [ebp-24h]
00934001 call std::vector<int,std::allocator<int> >::_unchecked_begin (09311feh)
00934006 mov dword ptr [ebp-30h],eax
// std::vector<int,std::allocator<int> >::end() 结果保存在 dword ptr [ebp-3ch]
00934009 mov ecx,dword ptr [ebp-24h]
0093400c call std::vector<int,std::allocator<int> >::_unchecked_end (09312c1h)
00934011 mov dword ptr [ebp-3ch],eax
// 跳转 for 循环的条件比较
00934014 jmp main+0bfh (093401fh)
// 迭代器加1
00934016 mov eax,dword ptr [ebp-30h]
00934019 add eax,4
0093401c mov dword ptr [ebp-30h],eax
// eax = dword ptr [ebp-30h]
// eax 和 vector::end() 比较,如果相等则跳出循环
0093401f mov eax,dword ptr [ebp-30h]
00934022 cmp eax,dword ptr [ebp-3ch]
00934025 je main+0e2h (0934042h)
// 将 dword ptr [ebp-30h] 迭代器指向的整形数值取出来,放到 dword ptr [ebp-48h]
00934027 mov eax,dword ptr [ebp-30h]
0093402a mov ecx,dword ptr [eax]
0093402c mov dword ptr [ebp-48h],ecx
{
printf( "num = %d\n", num );
// 从 dword ptr [ebp-48h] 取出整形数值,压栈
// 将 "num = %d\n" 压栈
// 调用 printf
0093402f mov eax,dword ptr [ebp-48h]
00934032 push eax
00934033 push offset string "num = %d\n" (093bc88h)
00934038 call _printf (093153ch)
0093403d add esp,8
}
// 跳转到迭代器加1位置
00934040 jmp main+0b6h (0934016h)
return 0;
00934042 mov dword ptr [ebp-130h],0
// vecotr析构
0093404c lea ecx,[numbers]
0093404f call std::vector<int,std::allocator<int> >::~vector<int,std::allocator<int> > (0931078h)
// 将返回值0放入eax寄存器
00934054 mov eax,dword ptr [ebp-130h]
}
// 出栈
0093405a push edx
0093405b mov ecx,ebp
0093405d push eax
0093405e lea edx,ds:[93408ch]
00934064 call @_rtc_checkstackvars@8 (09313f7h)
00934069 pop eax
0093406a pop edx
0093406b pop edi
0093406c pop esi
0093406d pop ebx
0093406e mov ecx,dword ptr [ebp-4]
00934071 xor ecx,ebp
00934073 call @__security_check_cookie@4 (0931415h)
00934078 add esp,150h
0093407e cmp ebp,esp
00934080 call __rtc_checkesp (0931212h)
00934085 mov esp,ebp
00934087 pop ebp
00934088 ret
上一篇: 游泳时如何自救 游泳时出现意外的自救方法