在C ++中是否有最大数组长度限制?
C ++中数组的最大长度是多less?
这是一个C + +的限制还是依赖于我的机器? 它可以调整吗? 它取决于数组的types?
我能否以某种方式打破这一限制,还是必须寻找更好的信息存储方式? 而最简单的方法是什么?
我所要做的就是在数组中存储long long long,我正在Linux环境中工作。 我的问题是:我需要做什么,如果我需要存储N长整数与N> 10位数组的数组?
我需要这个,因为我正在为学校编写一些密码algorithm(例如p-Pollard),并打到整数和长度的数组表示。
有两个限制,都不是由C ++强制执行,而是由硬件执行。
第一个限制(永远不应该达到)由用于描述数组索引的大小types的限制(及其大小)来设置。 它由系统的std::size_t
可以采取的最大值给出。 该数据types应始终是系统的最大整数types。
另一个限制是物理内存限制。 arrays中的对象越大,越快达到此限制,因为内存已满。 例如,一个给定大小为n的vector<int>
通常需要大约四倍于typesvector<char>
的数组的内存(减去一个小的常量值)。 因此,在内存已满之前,一个vector<char>
可能比vector<int>
包含更多的项目。 原生C型数组int[]
和char[]
。
此外,这个上限可能会受到构造vector
的allocator
types的影响,因为allocator
可以自由地以任何想要的方式pipe理内存。 一个非常奇怪的但不可思议的分配器可以以一种对象的相同实例共享资源的方式来共享内存。 这样,你可以插入很多相同的对象到一个容器中,否则会占用所有可用的内存。
除此之外,C ++没有强制执行任何限制。
没有人提到堆栈的大小限制。
有两个地方可以分配内存:
- 在堆上(dynamic分配内存)。
此处的大小限制是可用硬件和操作系统通过使用其他设备临时存储未使用的数据(即将页面移动到硬盘)来模拟空间的能力的组合。 - 在堆栈上(本地声明的variables)。
这里的大小限制是编译器定义的(可能有硬件限制)。 如果你阅读编译器文档,你通常可以调整这个大小。
因此,如果你dynamic分配一个数组(限制很大,并由其他职位详细描述。
int* a1 = new int[SIZE]; // SIZE limited only by OS/Hardware
或者,如果数组在堆栈上分配,则受限于堆栈的大小。 NBvector和其他容器在堆栈中存在less量存在,但通常大部分数据将堆在堆上。
int a2[SIZE]; // SIZE limited by COMPILER to the size of the stack frame
从实际而非理论的angular度来看,在32位Windows系统上,单个进程可用的最大内存总量为2 GB。 你可以通过使用更多物理内存的64位操作系统来打破限制,但是这样做还是寻找替代品取决于你的预期用户和他们的预算。 你也可以使用PAE来扩展它。
数组的types非常重要,因为在许多编译器上默认的结构alignment方式是8字节,如果内存使用是一个问题,这是非常浪费的。 如果您使用Visual C ++来定位Windows,请检查#pragma pack指令作为克服此问题的一种方法。
另一件事是看内存中的压缩技术可以帮助你,比如稀疏matrix,dynamic压缩等等。这同样是高度依赖于应用程序的。 如果你编辑你的post来提供更多关于数组中实际内容的信息,你可能会得到更多有用的答案。
编辑:给你一些关于你的确切需求的更多信息,你的存储需求看起来在未压缩的7.6 GB和76 GB之间,这需要一个相当昂贵的64位盒子作为一个数组存储在C ++的内存中。 这就提出了一个问题:为什么要将数据存储在内存中,在哪里假设访问速度,并允许随机访问。 将数据存储在数组之外的最好方法是基于您想要访问的方式。 如果您需要随机访问数组成员,那么对于大多数应用程序来说,这往往是将数据集合分组的方式,这些数据集可能同时被访问。 例如,在大型地理信息系统和空间数据库中,数据经常被地理区域平铺。 在C ++编程术语中,您可以覆盖[]数组运算符以根据需要从外部存储中获取部分数据。
我会同意上述,如果你是初始化你的arrays
int myArray[SIZE]
那么SIZE受限于整数的大小。 但是你总是可以malloc一块内存,并有一个指向它的指针,就像你想要的一样大,只要malloc不返回NULL。
以前的答案中提到了我不认为的一件事。
当人们在devise中使用这些东西时,我总是感觉到重构意义上的“难闻的气味”。
从效率angular度和性能angular度来看,这是一个巨大的arrays,可能不是表示数据的最佳方式。
干杯,
抢
如果您必须处理大量的数据,则需要将其分解为可pipe理的块。 它不会在任何小型计算机上都适合内存。 您可以从磁盘加载一部分数据(无论是否合理),执行计算并对其进行更改,将其存储到磁盘,然后重复,直到完成。
总结回应,扩展它们,直接回答你的问题:
不,C ++不会对数组的维度施加任何限制。
但是,由于arrays必须存储在内存中的某个位置,因此计算机系统的其他部分施加的与内存相关的限制也适用。 请注意,这些限制不直接与数组的维数 (=元素数量)相关,而与其大小 (=所占内存的数量)直接相关。 数组的尺寸( D )和内存中的尺寸( S )是不一样的,因为它们与单个元素( E )所占用的内存相关: S = D * E。
现在E取决于:
- 数组元素的types(元素可以更小或更大)
- 内存alignment(为了提高性能,元素被放置在某些值的乘法地址上,这就引入了
元素之间的“浪费空间”(填充) - 对象的静态部分的大小(在面向对象的编程中,同一types的对象的静态部分只存储一次,与这种同types对象的数量无关)
还要注意,通常通过在堆栈(作为自动variables: int t[N]
)或堆(使用malloc()
/ new
dynamic重定位或使用STL机制)上分配数组数据来获得不同的与内存相关的限制,在进程内存的静态部分(作为静态variables: static int t[N]
)。 即使在堆上分配时,堆栈上仍然需要less量内存来存储对堆内存块的引用(但这通常是微不足道的)。
size_t
types的大小对程序员没有任何影响(我假设程序员使用size_t
types进行索引,因为它是为它devise的),因为编译器提供者必须将它定义为一个足够大的整数types,以解决可能的最大内存量给定的平台架构。
内存大小的限制源于此
- 进程可用的内存量(对于32位应用程序(即使在64位操作系统内核上,限制为2 ^ 32字节),
- 进程内存的划分(例如为堆栈或堆devise的进程内存量)
- 物理内存的碎片化(许多分散的小型空闲内存碎片不适用于存储一个单片结构),
- 物理内存量,
- 和虚拟内存的数量。
它们不能在应用程序级进行“调整”,但可以自由使用不同的编译器(以更改堆栈大小限制),或将应用程序移植到64位,或将其移植到另一个操作系统,或更改物理/ (虚拟?物理?)机器的虚拟内存configuration。
将所有上述因素作为外部干扰并因此作为运行时错误的可能来源并非罕见(甚至是可取的),并且仔细检查和响应程序代码中与存储器分配相关的错误。
所以最后:虽然C ++没有任何限制,但在运行代码时仍然需要检查与内存相关的不利条件… 🙂
正如许多优秀的答案所指出的,有很多限制取决于您的C ++编译器,操作系统和计算机特性的版本。 不过,我build议在Python上使用以下脚本来检查机器上的限制。
它使用二进制search,每次迭代检查中间大小是否可能通过创build一个代码,试图创build一个大小的数组。 该脚本试图编译它(对不起,这部分只适用于Linux),并根据成功调整二进制search。 一探究竟:
import os cpp_source = 'int a[{}]; int main() {{ return 0; }}' def check_if_array_size_compiles(size): # Write to file 1.cpp f = open(name='1.cpp', mode='w') f.write(cpp_source.format(m)) f.close() # Attempt to compile os.system('g++ 1.cpp 2> errors') # Read the errors files errors = open('errors', 'r').read() # Return if there is no errors return len(errors) == 0 # Make a binary search. Try to create array with size m and # adjust the r and l border depending on wheather we succeeded # or not l = 0 r = 10 ** 50 while r - l > 1: m = (r + l) // 2 if check_if_array_size_compiles(m): l = m else: r = m answer = l + check_if_array_size_compiles(r) print '{} is the maximum avaliable length'.format(answer)
您可以将其保存到您的机器并启动它,它将打印您可以创build的最大尺寸。 我的机器是2305843009213693951。
正如已经指出的那样,arrays大小受限于您的硬件和操作系统(man ulimit)。 尽pipe如此,你的软件可能只会受到你的创造力的限制。 例如,你可以将你的“数组”存储在磁盘上吗? 你真的需要很长的时间吗? 你真的需要密集arrays吗? 你甚至需要一个数组?
一个简单的解决scheme是使用64位Linux。 即使您的arrays物理上没有足够的RAM,操作系统也会允许您像分配内存一样分配内存,因为您的进程可用的虚拟内存可能比物理内存大得多。 如果您确实需要访问数组中的所有内容,则相当于将其存储在磁盘上。 根据您的访问模式,可能会有更有效的方法来做到这一点(即:使用mmap(),或者简单地将数据顺序存储在一个文件中(在这种情况下,32位Linux就足够了))。
我会绕过这个做一个2ddynamic数组:
long long** a = new long long*[x]; for (unsigned i = 0; i < x; i++) a[i] = new long long[y];