std::vector<std::array<double,10>> 的零初始化

Zero initialization of std::vector<std::array<double,10>>

考虑以下代码

std::vector<std::array<double,10>> a(10);

如果我理解正确的话a不会被零初始化,因为 en.cppreference.com 关于 std::vector 构造函数说

  1. Constructs the container with count default-inserted instances of T. No copies are made.

因此,因为默认初始化 std::array<double, 10> 不会用零填充,所以 a 也不会包含零。

这是真的吗?

如何强制执行零初始化?

a.data() 会指向 100 个连续的 double 值吗?

编辑:

这是 gcc 10.2 上带有 -O2 的 godbolt 的输出

main:
        mov     edi, 800
        sub     rsp, 8
        call    operator new(unsigned long)
        mov     rdi, rax
        lea     rdx, [rax+800]
.L2:
        mov     QWORD PTR [rax], 0x000000000
        add     rax, 80
        mov     QWORD PTR [rax-72], 0x000000000
        mov     QWORD PTR [rax-64], 0x000000000
        mov     QWORD PTR [rax-56], 0x000000000
        mov     QWORD PTR [rax-48], 0x000000000
        mov     QWORD PTR [rax-40], 0x000000000
        mov     QWORD PTR [rax-32], 0x000000000
        mov     QWORD PTR [rax-24], 0x000000000
        mov     QWORD PTR [rax-16], 0x000000000
        mov     QWORD PTR [rax-8], 0x000000000
        cmp     rdx, rax
        jne     .L2
        mov     esi, 800
        call    operator delete(void*, unsigned long)
        xor     eax, eax
        add     rsp, 8
        ret

所以它似乎是零初始化的。那么问题仍然是为什么。

重载 default insert 个元素是正确的。

但是你必须继续阅读,因为默认插入意味着插入的值将是 value initialized,并且值初始化聚合(如 std::array)将值初始化聚合中的所有元素聚合。

并且 double 值的值初始化将与 zero-initialization 相同。

因此向量的每个数组中的所有元素都将被初始化为零。

您可以按照下面的演示程序所示执行此操作:

#include <iostream>
#include <array>
#include <vector>

int main() 
{
    std::vector<std::array<double,10>> v(10, { {} } );
    
    for ( const auto &a : v )
    {
        for ( const auto &item : a )
        {
            std::cout << item << ' ';
        }
        std::cout << '\n';
    }
    
    
    return 0;
}

程序输出为

0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 

为了确保您的数组是零初始化的,您可以添加一个 1 元素初始化列表作为 a 构造函数调用的第二个参数:

std::vector<std::array<double, 10>> a(10, { 0.0, });

这将使用该列表初始化 每个 元素(数组),因为它将使用 here in cppreference.

中描述的构造函数版本 #3

用于初始化每个数组的 'value' 参数将使用聚合初始化 (see here),这将对列表中的任何 'missing' 值进行零初始化。