通过引用http://www.cplusplus.com/doc/tutorial/dynamic/,可以说new
运算符返回指向新分配的内存块开头的指针。让我们再次假设任何指针都具有指针算术的特征,如果p + 1
是指针,p
指向内存中的下一个位置就是真的。
基于以上假设,我尝试了以下块,
#include <iostream>
using namespace std;
int main(){
int * ptr = (new int [4]) + 1;
ptr[3] = 2;
cout << ptr[3] << endl;
/*Before delete the dynamic allocated memory,
it should be necessary to let ptr point to the
beginning of it, add one line to do that:
--ptr;*/
delete [] ptr;
}
我预计ptr[3]
应该超出新分配的内存范围。但是,结果仍然是2
。为什么指针算术变得无用?或者它真的new Type
会返回*Type
的对象吗?
感谢您的帮助。
答案 0 :(得分:3)
确实如此。你需要注意不要这样做,因为(正如你所注意到的)这是一个经常无法检测到的错误。像valgrind这样的动态分析工具可以帮助诊断这些问题,但不是很完美。我预计
ptr[3]
应该超出新分配的内存范围。
然而,结果仍然是2。
这意味着在阵列末尾之外碰巧有可访问的内存,因此无法检测到无效访问。相反,它覆盖了不属于数组的内存 - 可能是未使用的,或者您可能已经覆盖了其他一些数据,这将导致以后出现令人困惑的错误。
为什么指针算术变得无用?
它与任何指针算法一样有用。指针算术无法检测到数组的结尾,因此如果超出范围,则会得到未定义的行为。
或者它真的
new Type
会返回*Type
的对象吗?
new Type[]
返回指向已分配数组的Type*
指针。其行为与任何其他指针一样,因此添加一个指针会指向第二个元素。
delete [] ptr
也会给出未定义的行为,因为ptr
不再指向已分配数组的开头。
答案 1 :(得分:2)
超越边界是未定义的行为。
使用differet编译器,不同的编译标志编译,甚至在不同的时间运行时,可能会得到不同的结果。您的计算机可能会烧断,显示器可能会烧坏。
返回正确的值也是未定义的行为之一。
答案 2 :(得分:1)
int * ptr = new int [4];
将指向ptr[0]
,所以
int * ptr = (new int [4]) + 1;
将指向ptr[1]
,除非您执行ptr
之类的操作,否则您将无法释放delete (ptr--)
;
答案 3 :(得分:1)
C / C ++允许您向/从超出范围的内存中分配/读取值,因为这是未定义的行为。
例如,这是有效的代码:
int *array = new int[10];
array[10] = 5;
std::cout<<array[10];
然而,这样做可能会损坏其他数据结构,如果它们恰好在您的阵列旁边分配了内存。