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 构造函数说
- 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' 值进行零初始化。
考虑以下代码
std::vector<std::array<double,10>> a(10);
如果我理解正确的话a
不会被零初始化,因为
en.cppreference.com 关于 std::vector 构造函数说
- 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' 值进行零初始化。