标准定义的 std::array 的大小
在 C++11 中,std::array
被定义为具有不比数组差的连续存储和性能,但我无法确定标准的各种要求是否意味着std::array 具有与普通数组相同的大小和内存布局.也就是说,您可以依靠 sizeof(std::array
还是特定于实现?
特别是,这是否保证按您期望的方式工作:
std::vector>x(M);typedef (*ArrayPointer)[N];ArrayPointer y = (ArrayPointer) &x[0][0];//像普通的多维数组一样使用 y
它适用于我尝试过的两个编译器(GNU 和英特尔).此外,我能找到的所有 3rd 方文档(像这样)都指出 std::array 只是与普通数组一样有效的内存,结合连续要求意味着它必须具有相同的内存布局.但是我在标准中找不到这个要求.
解决方案几乎需要.具体来说,第 23.3.2.1/2 节说:
<块引用>数组是一个聚合(8.5.1),可以用语法初始化
arraya = { 初始化列表};
<块引用>
其中 initializer-list
是以逗号分隔的列表,最多包含 N 个元素,其类型可转换为 T.
由于它是一个聚合,它不能使用任何类型的构造函数将初始化列表中的数据转换为正确的格式.那真的只剩下一种可能性:它唯一可以存储的东西就是值本身.
我想 std::array
可以在指定数据之后存储某种辅助数据,例如设置为某个预定义值的额外内存,所以如果你写到数组的末尾,你可能会改变那个数据.然后编译器/运行时会在关闭时检查这些值,如果您更改了这些值,请报告您的代码的未定义行为.
也有可能编译器可以为 std::array
做不同的填充/对齐而不是内置数组.一个明显的例子是支持超级对齐要求,例如与英特尔的 SSE 指令一起使用的数据.内置数组不能支持超对齐,但我认为std::array
的规范可能勉强够宽松允许.
底线:不考虑可能存在多少可能性的问题,很明显std::array
不一定要遵循您所询问的规则.
In C++11 std::array
is defined to have contiguous storage and performance that is no worse than an array, but I can't decide if the various requirements of the standard imply that std::array has the same size and memory layout as a normal array. That is can you count on sizeof(std::array<int,N>) == sizeof(int)*N
or is that implementation specific?
In particular, is this guaranteed to work the way you would expect it to:
std::vector< std::array<int, N> > x(M);
typedef (*ArrayPointer)[N];
ArrayPointer y = (ArrayPointer) &x[0][0];
// use y like normal multidimensional array
It works in the two compilers I tried (GNU & Intel). Furthermore, all the 3rd party documentation I could find (like this), states that std::array is just as memory efficient as a plain array, which combined with the contiguous requirement would imply that it must have identical memory layout. However I can't find this requirement in the standard.
解决方案It's nearly required. Specifically, §23.3.2.1/2 says:
An array is an aggregate (8.5.1) that can be initialized with the syntax
array<T, N> a = { initializer-list };
where
initializer-list
is a comma-separated list of up to N elements whose types are convertible to T.
Since it's an aggregate, it can't use any sort of constructor to convert the data in the initializer-list to the correct format. That really only leaves one possibility: about the only thing it can store are the values themselves.
I suppose it would be possible for an std::array
to store some sort of auxiliary data following the specified data, such as extra memory set to some predefined value, so if you write past the end of the array, you'd probably change that data. The compiler/run-time would then check those values at shut-down, and if you'd changed the values, report your code's undefined behavior.
It's also possible that a compiler could do padding/alignment differently for an std::array
than for a built-in array. One obvious example for which this could even be desirable would be to support super-alignment requirements, such as data for use with Intel's SSE instructions. A built-in array can't support super-alignment, but I think the specification of std::array
might be barely loose enough to allow it.
Bottom line: without getting into questions of how many possibilities might exist, it's pretty clear that std::array
doesn't necessarily have to follow the rule you're asking about.
相关文章