使用指针对2D数组进行非访问冲突

时间:2013-12-14 05:29:45

标签: c++ pointers multidimensional-array

我正在尝试使用指针创建一个2D动态数组:

int** Grid;
Grid = new int*[5];
for (int i=0;i<5;i++)   { Grid[i] = new int[5]; }
std::cout << Grid[4][300] << std::endl;   // output: -17891602
std::cout << Grid[5][0] << std::endl;     // access violation

我需要数组具有特定大小,这就是我不使用静态数组的原因。 正如您所看到的,虽然我正在制作一个5x5阵列,但调试器在尝试读取Grid [4] [300]时没有给出错误。有人可以请你告诉我为什么会这样?

对于第二维,这似乎只是如此。 (试图读取Grid [5] [0]会给出访问冲突错误)如果我错了,请纠正我,但从技术上讲,我真的在创建一个指针数组?

我期待Grid [5] [0]的例外。我真正没有得到的是为什么Grid [4] [300]没有错误。有人可以告诉我如何使用动态数组,比如5x5维度?

3 个答案:

答案 0 :(得分:1)

你从未在for-loop中检查i < 5初始化Grid [5]。
如果我小于5,则它永远不会在for循环中用作5。

请记住,数组将0作为一个位置。

这意味着int arr[5]只能用0-4编制索引,任何或多或少都会导致访问冲突


[300]没有抛出访问冲突的原因是因为您索引指针而不是定义的数组。


另外,不要忘记初始化数组中的值(最可能为0)。您可能不希望在数据中显示-1994021等意外数字。
memset非常善于这样做。

答案 1 :(得分:1)

问题是数组计数为0。因此,如果您使用for (int i = 0; i < Size; ++i)初始化它,那么数组中的第一个内存空间将是[0] [0]

考虑以下代码:

#include <iostream>

using namespace std;

int main () {
    int Size = 5;
    int **Grid;
    Grid = new int* [Size];
    for (int i = 0; i < Size; ++i)
        Grid[i] = new int [Size];

    for (int i = 0; i < Size; ++i)
        for (int j = 0; j < Size; ++j)
            cin >> Grid[i][j];

    cout << Grid[4][4];
    return 0;
}

如果将其放入IDE并进行编译,则应该打印最后一个元素的值。那是因为你有数组的以下位置:

Grid[0][0];
Grid[0][1];
Grid[0][2];
Grid[0][3];
Grid[0][4];
...
Grid[4][4];

在动态分配任何类型的数组时,请记住,还必须提供delete []。

所以我放置的代码看起来是这样的:

#include <iostream>

using namespace std;

int main () {
    int Size = 5;
    int **Grid;
    Grid = new int* [Size];
    for (int i = 0; i < Size; ++i)
        Grid[i] = new int [Size];

    for (int i = 0; i < Size; ++i)
        for (int j = 0; j < Size; ++j)
            cin >> Grid[i][j];

    cout << Grid[4][4];

    for (int i = 0; i < Size; ++i)
        delete [] Grid[i];
    delete [] Grid;
    return 0;
}

这是因为您正在使用Stack。 - &GT; http://en.wikipedia.org/wiki/Stack_%28abstract_data_type%29

我希望这能为你澄清一些事情。祝你好运!

答案 2 :(得分:0)

在c和c ++中,如果您尝试访问的索引大于声明的索引,则不会出现编译错误和运行时错误 例如。

  

int a [10];
  的std :: COUT&LT;&LT;一个[20]; //会打印一些垃圾值

所以这就解释了为什么 std :: cout&lt;&lt;网格[4] [300]&lt;&lt; std :: endl; 正在输出:-17891602,因为第二个维度只是整数数组。

然而,如果您声明一个指针数组并尝试访问更大的索引,那么您将在运行时获得访问冲突错误或分段错误
例如

  

int * a;
  a = new int [5];
  的std :: COUT&LT;&LT;一个[20]; //会产生细分错误

所以这就解释了为什么 std :: cout&lt;&lt;网格[5] [0]&lt;&lt; std :: endl; 或第一维中任何大于声明值的值都会产生错误,因为第一维应该是指向某个包含整数值的合法位置的指针
但是在尝试访问更大的索引时,可能产生一个非法地址的垃圾值,从而导致分段错误。
希望这会有所帮助。