据我所知
int* p = new int();
类似于用构造函数创建int类型。如果是这样,为什么下面的代码像数组一样工作?
int* p = new int();
*p = 5;
p[1] = 15;
for (int i = 0; i < 2; i++)
cout << p[i] << endl;
5
15
为什么new int()在c++中像数组一样工作?
p[1]
相当于*(p + 1)
,它只是对指针解引用来访问存储在它指向的内存位置的值,表示法类似于数组表示法,它被允许并且首选指针表示法,因为它更具可读性。
据我理解
int* p = new int();
类似于用构造函数创建
int
。
是的,但这不是全部,您还恰好为一个int
分配内存,并将内存地址分配给指针p
。
请注意,它可能是int* p = new int[2]
,它是完全相同的指针,但在这种情况下,由new
返回的内存块适用于2int
,而不仅仅是一个,顺便说一句,这将使您的代码的其余部分有效,除了您不delete
由new
分配的内存,这将导致内存泄漏。
现在考虑下面的代码:
int arr[10];
int* p = arr;
在这种情况下,您有完全相同的指针,但它将指向具有自动存储持续时间的数组的第一个元素。
指针不知道它指向多少内存,因为它指向的是给定内存块中的第一个元素,对于程序来说,该块有多大并不明显。当为指针建立索引时,程序员有责任不占用该内存。
需要注意的一件重要的事情是,在某些情况下,其他语言可能会阻止你涉足其中,但c++不会,它相信程序员会写出正确的代码,这就是为什么当一个c++程序员通常比较困难的原因。
正如已经指出的,您的程序在访问p[1]
时发生未定义行为。注意链接资源的第一个短语,它简单地声明:
[未定义行为]如果违反了语言的某些规则,则使整个程序无意义
这就是这里的情况,您正在访问的内存位于手动内存分配所定义的边界之外。事实上,输出是你所期望的是一个(坏的,我会说)运气的问题,它可能今天输出正确的结果,明天崩溃,谁知道呢。
从上面的例子可以看出,这种情况很难诊断,对于3个例子来说,它是完全相同的类型。
在任何情况下,都有像这样诊断内存问题的方法,例如valgrind和gcc地址消毒器等。
附带说明,避免使用原始指针,如果可能,使用智能指针或c++容器之一。
我还鼓励您获得一些有关OOP RAII原则的相关主题的知识。
为什么下面的代码像数组一样工作?
它不。程序有未定义行为意思是它仍然是错误的,即使它没有这么明确地说,而且"似乎在工作"。这是由于在你的程序中使用了表达式p[1]
和p[i]
。
未定义行为意味着任何1都可能发生,包括但不限于给出预期输出的程序。但是从不依赖(或基于)具有未定义行为的程序的输出。程序可能会崩溃。
所以你看到的输出(可能看到的)是未定义行为的结果。正如我所说的不要依赖于输出一个有UB的项目程序可能会崩溃。
因此,使程序正确的第一步是删除UB。当且仅当你可以开始对程序的输出进行推理。
1对于未定义行为的更准确的技术定义,请参见这里提到的:对程序的行为没有限制。