“(新类型[n])+ 1”返回什么?

时间:2014-01-13 11:27:05

标签: c++ pointers pointer-arithmetic

通过引用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的对象吗?

感谢您的帮助。

4 个答案:

答案 0 :(得分:3)

  

我预计ptr[3]应该超出新分配的内存范围。

确实如此。你需要注意不要这样做,因为(正如你所注意到的)这是一个经常无法检测到的错误。像valgrind这样的动态分析工具可以帮助诊断这些问题,但不是很完美。

  

然而,结果仍然是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];

然而,这样做可能会损坏其他数据结构,如果它们恰好在您的阵列旁边分配了内存。