首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >initializer_list后面“隐藏数组”的存储

initializer_list后面“隐藏数组”的存储
EN

Stack Overflow用户
提问于 2012-08-29 15:08:30
回答 2查看 734关注 0票数 7

在C++11标准中,有一个关于支持统一初始化的数组的说明,该数组声明:

如果可以这样分配具有相同初始化程序的显式数组,则实现可以在只读内存中分配数组。

GCC/Clang/VS是否利用了这一点?还是每次使用此特性的初始化都需要堆栈上的额外数据,以及这个隐藏数组的额外初始化时间?

例如,给出以下示例:

代码语言:javascript
复制
void function()
{
    std::vector<std::string> values = { "First", "Second" };
...

上面提到的每个编译器会将支持数组存储到与声明为static const的变量相同的内存中的统一初始化中吗?在调用函数时,每个编译器会初始化支持数组,还是在应用程序初始化时初始化?(我说的不是要创建的std::initializer_list<std::string>,而是它所指的“隐藏数组”。

EN

回答 2

Stack Overflow用户

发布于 2012-09-25 15:23:47

这是我至少为GCC回答自己的问题的尝试。我对gcc的汇编程序输出的理解不是很好,所以请根据需要进行更正。

使用initializer_test.cpp

代码语言:javascript
复制
#include <vector>

int main()
{
    std::vector<long> values = { 123456, 123457, 123458 };
    return 0;
}

并使用以下命令行使用gcc v4.6.3编译:

代码语言:javascript
复制
g++ -Wa,-adhln -g initializer_test.cpp -masm=intel -std=c++0x -fverbose-asm | c++filt | view -

我得到了以下输出(减少到有希望的相关部分):

代码语言:javascript
复制
   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()  #

代码语言:javascript
复制
 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似乎得到了优化:

代码语言:javascript
复制
  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看起来是非常理想的。

票数 2
EN

Stack Overflow用户

发布于 2012-09-23 17:19:40

首先: VC++最初发布的VS11=VS2012版本不支持初始化程序列表,所以这个问题对于VS atm来说有点小问题,但我相信他们会修补这个问题,几个月(或几年)就会变得相关了。

作为附加信息,我将添加VS 2012对本地数组初始化所做的操作,对于实现初始化程序列表时,每个人都可能得出自己的结论:

下面是内置数组的初始化,VC++2012在编译器的默认release mode中显示了哪些内容:

代码语言:javascript
复制
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  

...

因此,这个数组是在函数执行时创建/填充的,不涉及“静态”存储。

票数 -2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12181080

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档