我需要在std::vector
中存储大量元素(超过unsigned int允许的2 ^ 32-1)。据我所知,这个数量受std::size_t
unsigned int类型的限制。我可以通过转换为std::size_t
来更改此unsigned long
吗?它会解决这个问题吗?
如果那是不可能的,假设我用64位编译。这会在没有任何修改的情况下解决问题吗?
答案 0 :(得分:6)
size_t
是一种可以保存任何可分配内存块大小的类型。因此,您无法分配比size_t
更适合的内存,因此无法以任何方式存储更多元素。
以64位编译将允许它,但意识到阵列仍然需要适合内存。 2 32 是40亿,所以你要超过4 * sizeof(元素)GiB的内存。超过8 GiB的RAM仍然很少,因此看起来不合理。
我建议用STXXL中的一个替换矢量。它使用外部存储,因此您的向量不受RAM的限制。该图书馆声称可以轻松处理数TB的数据。
(编辑)迂腐:size_t
需要保持最大单个对象的大小,而不一定是所有可用内存的大小。在分段存储器模型中,当每个对象必须存在于单个段中时,它仅需要适应偏移,但是对于不同的段,可以访问更多的存储器。甚至可以在x86上使用它与PAE,“长”内存模型。但是我没有看到任何人真正使用它。
答案 1 :(得分:3)
有很多事情要说。
首先,分别关于32位系统和64位系统上 std::size_t
的大小。这就是标准所说的关于std::size_t
(§18.2/ 6,7)的内容:
6类型
size_t
是一种实现定义的无符号整数类型,其大小足以包含大小 以字节为单位的任何对象。7 [注意:建议实现选择
ptrdiff_t
和size_t
整数的类型 转换等级(4.13)不大于signed long int
的转换等级,除非需要更大的尺寸 包含所有可能的值。 - 结束说明]
由此可见,std::size_t
在32位系统上至少 32位,并且64位至少 64位比特系统。它可能更大,但显然没有任何意义。
第二,关于类型转换的想法:为了实现这一点,即使在理论上,你也必须施展(或者更确切地说) :重新定义)std::vector
本身实现中的类型,无论它出现在何处。
第三次,当你说你需要“32位”的超大矢量时,这是否意味着你想在32位系统上使用它?在这种情况下,正如其他人已经指出的那样,你想要的是不可能的,因为32位系统根本没有那么多内存。
但是,第四,如果您想要的是在64位计算机上运行程序,并且只使用32位数据类型来引用数字的元素,但可能是一个64位类型来指代以字节为单位的总大小,那么std::size_t
是不相关的,因为它用于指代元素的总数和各个元素的索引,但是不是以字节为单位的大小。
最后,如果您使用的是64位系统,并希望使用类似std::vector
的极端比例,那肯定是可能的。具有32 GB,64 GB甚至1 TB主内存的系统可能不是很常见,但绝对可用。
然而,要实现这样的数据类型,只需在一个连续的块中分配千兆字节的内存 (这是std::vector
的作用),原因如下:
<强>结论强>
A)如果您使用的是32位系统,并且想要使用大的矢量,那么使用基于磁盘的方法(如@JanHudec建议的那种方法)是唯一的东西这是可行的。
B)如果您可以访问具有数十或数百GB的大型64位系统,则应该查看将整个内存区域划分为块的实现。基本上类似于std::vector<std::vector<T>>
的东西,其中每个嵌套向量代表一个块。如果所有块都已满,则附加一个新块等。为此也可以直接实现迭代器类型。当然,如果你想进一步优化它以利用多线程和NUMA功能,它将变得越来越复杂,但这是不可避免的。
答案 2 :(得分:0)
vector
可能是您错误的数据结构。它需要存储在单个内存块中,这受到size_t
大小的限制。这可以通过编译64位系统来增加,但是你不能在可能需要的32位系统上运行。
如果您不需要vector
的特定特征(特别是O(1)查找和连续的内存布局),则std::list
等其他结构可能适合您,没有大小限制除了计算机可以物理处理的内容,因为它是链接列表而不是方便包装的数组。