c – 在initializer_list后面存储“隐藏数组”

前端之家收集整理的这篇文章主要介绍了c – 在initializer_list后面存储“隐藏数组”前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
在C 11标准中,有一个关于支持统一初始化的阵列的说明,其中指出:

The implementation is free to allocate the array in read-only memory if an explicit array with the same initializer could be so allocated.

GCC/C++lang / VS会利用这个吗?或者使用此功能的每个初始化是否受到堆栈上的其他数据的影响,以及此隐藏阵列的额外初始化时间?

例如,给出以下示例:

void function()
{
    std::vector<std::string> values = { "First","Second" };
...

上面提到的每个编译器是否将后备数组存储在与变量声明的静态const相同的内存中的统一初始化中?当调用函数或应用程序初始化时,每个编译器是否会初始化后备数组? (我不是在讨论将要创建的std :: initializer_list< std :: string>而是它所引用的“隐藏数组”.

解决方法

这是我尝试至少回答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,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,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,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,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,D.11805
 131 0036 E8000000      call    operator delete(void*)  #

总而言之,std :: initializer_list在gcc中看起来非常优秀.

猜你在找的C&C++相关文章