在c++中为数组分配特定数量的内存的目的是什么?
What is the purpose of allocating a specific amount of memory for arrays in C++?
我是一名本学期选修c++数据结构课程的学生,今晚我遇到了一些我不太明白的东西。假设我要在堆上创建一个指向数组的指针:
int* arrayPtr = new int [4];
我可以使用指针语法访问这个数组
int value = *(arrayPtr + index);
但是如果我要在为数组分配的空间结束后立即向内存位置添加另一个值,那么我就可以访问它
*(arrayPtr + 4) = 0;
int nextPos = *(arrayPtr + 4);
//the value of nextPos will be 0, or whatever value I previously filled that space with
*(arrayPtr + 4)在内存中的位置超过了为该数组分配的空间的末尾。但据我所知,上述情况不会造成任何问题。因此,除了c++的要求之外,为什么在声明数组时还要给数组指定一个特定的大小呢?
当您超过分配的内存的末尾时,您实际上正在访问其他对象的内存(或者现在是空闲的,但以后可能会更改的内存)。因此,它将给您带来问题。尤其是如果你想给它写点什么。
我可以使用指针语法访问这个数组
int value = *(arrayPtr + index);
是的,但是不要。使用arrayPtr[index]
*(arrayPtr + 4)在内存中的位置超过了为该数组分配的空间的末尾。但据我所知,上述情况不会造成任何问题。
你理解错了。哦,太错了。你调用了未定义行为而未定义行为就是未定义的。它可能工作了一个星期,然后下周的某一天坏了,你会想知道为什么。如果您事先不知道集合大小,请使用动态的东西,如vector
,而不是数组。
是的,在C/c++中,您可以访问您声称已分配的空间之外的内存。有时。这就是所谓的未定义行为。
基本上,您已经告诉编译器和内存管理系统,您需要存储四个整数的空间,并且内存管理系统为您分配了存储四个整数的空间。它给了你一个指向那个空间的指针。在内存管理器的内部记帐中,这些内存字节现在被占用,直到调用delete[] arrayPtr;
。
在一个简单的示例程序中,就像你的例子一样,它只分配几个字节,不分配其他任何东西,很可能下一个字节属于你的程序,并且没有被占用。如果该数组是程序中唯一动态分配的内存,那么可能, 可能可以安全运行到末尾。
但是在一个更复杂的程序中,有多个动态内存分配和释放,特别是在内存页边缘附近,你真的没有很好的方法知道你请求的内存之外的任何字节包含什么。因此,当您写入new
中所要求的内存之外的字节时,您基本上可以写入任何内容。
这就是未定义行为的由来。因为你不知道你写的那个地方有什么,你不知道结果会发生什么。下面是一些可能发生的事情的例子:
当你写内存时,内存没有被分配。在这种情况下,数据很好,似乎没有什么不好的事情发生。但是,如果以后的内存分配使用了该空间,那么您尝试放在那里的任何内容都将丢失。
当您写入内存时,内存已被分配。在这种情况下,恭喜你,你只是覆盖了程序中其他数据结构中的一些随机字节。想象一下,用随机数据替换某个对象中的变量,并考虑这对程序意味着什么。也许其他地方的列表现在有错误的计数。也许一个字符串现在有一些随机的前几个字符的值,或者现在是空的,因为你用零替换了这些字符。
数组是在页的边缘分配的,所以下一个字节不属于您的程序。该地址在程序的分配之外。在这种情况下,操作系统检测到您正在访问不属于您的随机内存,并立即使用
SIGSEGV
终止您的程序。
基本上,未定义行为意味着你正在做一些非法的事情,但是因为C/c++的设计是为了快速,语言设计者没有包括一个显式的检查来确保你没有违反规则,像其他语言(例如Java, c#)。他们只是把违反规则的行为列为未定义的,然后编译器的人可以让输出更简单,更快的代码,因为没有进行数组边界检查,如果你违反了规则,那是你自己的问题。
所以,是的,这有时有效,但永远不要依赖它。
在纯抽象的设置中不会造成任何问题,您只需要担心算法的逻辑是否合理。在这种情况下,根本没有理由声明数组的大小。但是,您的计算机存在于物理世界中,并且只有有限的内存。当你分配内存时,你是在请求操作系统允许你使用计算机有限的内存。如果超出了这个范围,操作系统应该阻止您,通常是通过杀死您的进程/程序。
是的,你必须把它写为arrayptr[index],因为*(arrayptr + 4)在内存中的位置超过了你为数组分配的空间的末尾。数组的大小一旦分配就不能扩展,这是c++的缺陷。
- 这个指针和内存代码打印是什么?我不知道是打印垃圾还是如何打印我需要的值
- 使用共享指针时,从共享指针本身释放内存的机制是什么
- 具有相同特征的两个对象是否只在内存中存储一次?无论定义它们的函数是什么,都是不同的
- 删除类成员的动态分配内存的最佳方法是什么
- 我在 2D 数组的动态内存分配中遇到了一些奇怪的代码C++? 请解释一下这是什么?
- 释放 std::vector 中指针内存的最有效方法是什么?
- 释放分配给大量矢量的内存的最有效方法是什么?
- 内存中的值是什么?
- 将内存分配给 2D 数组时,“new int*[rowCount];”的含义是什么?是 2D 数组,是指向数组的指针数组
- 为循环中多次调用的函数返回值预分配内存的正确方法是什么
- 使用 CFFI 释放内存时"MemoryError: Stack overflow"是什么意思?
- 函数不受主内存约束的函数所需的复杂性是什么?
- 当某些错误可以接受时,顺序加载存储原子的内存顺序应该是什么
- 获取释放内存顺序与顺序一致性不同的实际示例是什么?
- 数组向量的内存布局是什么
- 跳过的内存地址是什么?
- C/C++ 三维数组如何在内存中存储,以及遍历它的最快方法是什么
- 在内存使用或编译时间方面更好的是什么
- 在Windows上打开文件的内存开销是什么?
- 内存泄漏的长期后果是什么?