在C++11标准中,有一个关于支持统一初始化的数组的说明,该数组声明:
如果可以这样分配具有相同初始化程序的显式数组,则实现可以在只读内存中分配数组。
GCC/Clang/VS是否利用了这一点?还是每次使用此特性的初始化都需要堆栈上的额外数据,以及这个隐藏数组的额外初始化时间?
例如,给出以下示例:
void function()
{
std::vector<std::string> values = { "First", "Second" };
...上面提到的每个编译器会将支持数组存储到与声明为static const的变量相同的内存中的统一初始化中吗?在调用函数时,每个编译器会初始化支持数组,还是在应用程序初始化时初始化?(我说的不是要创建的std::initializer_list<std::string>,而是它所指的“隐藏数组”。
发布于 2012-09-25 15:23:47
这是我至少为GCC回答自己的问题的尝试。我对gcc的汇编程序输出的理解不是很好,所以请根据需要进行更正。
使用initializer_test.cpp
#include <vector>
int main()
{
std::vector<long> values = { 123456, 123457, 123458 };
return 0;
}并使用以下命令行使用gcc v4.6.3编译:
g++ -Wa,-adhln -g initializer_test.cpp -masm=intel -std=c++0x -fverbose-asm | c++filt | view -我得到了以下输出(减少到有希望的相关部分):
5:initializer_test.cpp **** std::vector<long> values = { 123456, 123457, 123458 };
100 .loc 2 5 0
101 0009 488D45EF lea rax, [rbp-17] # tmp62,
102 000d 4889C7 mov rdi, rax #, tmp62
103 .cfi_offset 3, -24
104 0010 E8000000 call std::allocator<long>::allocator() #
104 00
105 0015 488D45D0 lea rax, [rbp-48] # tmp63,
106 0019 BA030000 mov edx, 3 #, <-- Parameter 3
106 00
107 001e BE000000 mov esi, OFFSET FLAT:._42 #, <-- Parameter 2
107 00
108 0023 4889C7 mov rdi, rax #, tmp63 <-- Parameter 1
109 0026 E8000000 call std::initializer_list<long>::initializer_list(long const*, unsigned long) #
109 00
110 002b 488D4DEF lea rcx, [rbp-17] # tmp64,
111 002f 488B75D0 mov rsi, QWORD PTR [rbp-48] # tmp65, D.10602
112 0033 488B55D8 mov rdx, QWORD PTR [rbp-40] # tmp66, D.10602
113 0037 488D45B0 lea rax, [rbp-80] # tmp67,
114 003b 4889C7 mov rdi, rax #, tmp67
115 .LEHB0:
116 003e E8000000 call std::vector<long, std::allocator<long> >::vector(std::initializer_list<long>, std::allocator<long> const&) #
116 00
117 .LEHE0:
118 .loc 2 5 0 is_stmt 0 discriminator 1
119 0043 488D45EF lea rax, [rbp-17] # tmp68,
120 0047 4889C7 mov rdi, rax #, tmp68
121 004a E8000000 call std::allocator<long>::~allocator() #和
1678 .section .rodata
1679 0002 00000000 .align 16
1679 00000000
1679 00000000
1679 0000
1682 ._42:
1683 0010 40E20100 .quad 123456
1683 00000000
1684 0018 41E20100 .quad 123457
1684 00000000
1685 0020 42E20100 .quad 123458
1685 00000000 现在,如果我在x86-64 System V AMD64 ABI调用约定(我对代码清单进行了注释的参数)的上下文中正确理解了第109行的调用,这将显示支持数组存储在.rodata__中,我将其视为与静态const数据相同的内存。至少对gcc来说是4.6。
执行类似的测试,但在打开优化(-O2)之后,initializer_list似乎得到了优化:
70 .file 2 "/usr/include/c++/4.6/ext/new_allocator.h"
71 .loc 2 92 0
72 0004 BF180000 mov edi, 24 #,
72 00
73 0009 E8000000 call operator new(unsigned long) #
73 00
74 .LVL1:
75 .file 3 "/usr/include/c++/4.6/bits/stl_algobase.h"
76 .loc 3 366 0
77 000e 488B1500 mov rdx, QWORD PTR ._42[rip] # ._42, ._42
77 000000
90 .file 4 "/usr/include/c++/4.6/bits/stl_vector.h"
91 .loc 4 155 0
92 0015 4885C0 test rax, rax # D.11805
105 .loc 3 366 0
106 0018 488910 mov QWORD PTR [rax], rdx #* D.11805, ._42
107 001b 488B1500 mov rdx, QWORD PTR ._42[rip+8] # ._42, ._42
107 000000
108 0022 48895008 mov QWORD PTR [rax+8], rdx #, ._42
109 0026 488B1500 mov rdx, QWORD PTR ._42[rip+16] # ._42, ._42
109 000000
110 002d 48895010 mov QWORD PTR [rax+16], rdx #, ._42
124 .loc 4 155 0
125 0031 7408 je .L8 #,
126 .LVL3:
127 .LBB342:
128 .LBB343:
129 .loc 2 98 0
130 0033 4889C7 mov rdi, rax #, D.11805
131 0036 E8000000 call operator delete(void*) #总而言之,在gcc看来,std::initializer_list看起来是非常理想的。
发布于 2012-09-23 17:19:40
首先: VC++最初发布的VS11=VS2012版本不支持初始化程序列表,所以这个问题对于VS atm来说有点小问题,但我相信他们会修补这个问题,几个月(或几年)就会变得相关了。
作为附加信息,我将添加VS 2012对本地数组初始化所做的操作,对于实现初始化程序列表时,每个人都可能得出自己的结论:
下面是内置数组的初始化,VC++2012在编译器的默认release mode中显示了哪些内容:
int _tmain(int argc, _TCHAR* argv[])
{
00B91002 in al,dx
00B91003 sub esp,28h
00B91006 mov eax,dword ptr ds:[00B94018h]
00B9100B xor eax,ebp
00B9100D mov dword ptr [ebp-4],eax
00B91010 push esi
int numbers[] = {1,2,3,4,5,6,7,8,9};
00B91011 mov dword ptr [numbers],1
00B91018 mov dword ptr [ebp-24h],2
00B9101F mov dword ptr [ebp-20h],3
00B91026 mov dword ptr [ebp-1Ch],4
00B9102D mov dword ptr [ebp-18h],5
00B91034 mov dword ptr [ebp-14h],6
00B9103B mov dword ptr [ebp-10h],7
00B91042 mov dword ptr [ebp-0Ch],8
00B91049 mov dword ptr [ebp-8],9
...因此,这个数组是在函数执行时创建/填充的,不涉及“静态”存储。
https://stackoverflow.com/questions/12181080
复制相似问题