在我看来,这就是内存在C ++中的工作方式:
如果您使用new
,那么您要求编译器的实现从堆中提供一些内存(任何内存)。
如果你使用了放置新语法,那么你要求重新分配一个你已经知道地址的特定内存位置(让我们假设它也来自堆),这可能也是最初从{ {1}}运营商在某个时候。
我的问题是:
无论如何都知道程序可以使用哪些内存位置先验(即没有从new
运算符已经提供给您的堆中重新分配内存) ?
堆中的内存是否连续?如果是这样,你能找到它的起始位置和结束位置吗?
P.S。试着尽可能快地尽可能接近金属......
答案 0 :(得分:5)
不以任何便携方式。现代操作系统倾向于使用分页(也称为虚拟内存),因此可用内存量不是一个容易回答的问题。
如果你需要编写自己的堆,那么堆中的内存不需要是连续的,这不是很难做到的。
答案 1 :(得分:2)
程序“先验”可用的内存包含您定义的变量。编译器已准确计算出程序需要多少。没有什么“额外”你可以用来做别的事。
您需要动态创建的新对象是从免费存储(也称为堆)中分配的,可能是使用new
,但更常见的是使用库中的容器,如std::vector
。
语言标准没有详细说明它是如何工作的,只是如何使用它。
答案 2 :(得分:1)
这是一个非常困难的问题。在现代操作系统中,存在诸如存储器管理器的子系统。当您的程序执行new
运算符时,有两个选项:
无论如何都要先知道程序可以使用哪些内存位置(即没有从新运算符已经给你的堆中重新分配内存)?
我想强调它取决于操作系统的版本和环境。
堆中的内存是否连续?
不,它可能是非连续的。
答案 3 :(得分:1)
未定义从new
或malloc()
的连续调用中收到的地址的连续性。 C运行时和操作系统可以在连续new
的地址空间中自由地返回指针。 (事实上,它可能会这样做,因为好的分配器会根据分配的大小从不同的池中提取以减少碎片,并且这些池将位于不同的页面中。)
但是,new
中的 单分配中的字节保证是连续的,所以如果你这样做
int *foo = new int[1024 * 1024]
你会得到一百万个连续的单词。
如果你真的需要一个大的连续分配,你可能需要使用特定于操作系统的函数来执行此操作(除非有人隐藏了一些我不知道的Boost库)。在Windows上,VirtualAlloc()。在POSIX上,mmap()。