C++指针和多维数组的双重间接寻址



所以我一直在尝试更多地理解指针,我遇到了这个:

double **DPtr; // just for example

我已经读过它可以用来指向一个多维数组,但在我使用单个间接符号 ( * 之前我无法让它工作。

那么,如果我不能对多维数组使用双间接寻址,它的用途是什么?

我试图找到答案,但没有运气。

提前感谢您给我的任何信息! :)

你的问题不太清楚。您可以使用double**创建自己的 2-D 数组,并进行大量手动簿记:

const size_t dim1 = 10, dim2 = 20;
double **arr;
arr = new double*[dim1];
for (size_t idx = 0; idx < dim1; ++idx) {
  arr[idx] = new double[dim2];
}
double[4][5] = 3.14;

数组甚至可以是"锯齿状"的,因为对于每个"主"索引,每个"辅助"数组的大小都可以不同。

但是,它

实际上是一个指向数组的指针数组,它不是一个真正的二维数组,因为它在内存中不是连续的。如果您改为创建真正的二维数组:

double arr[dim1][dim2];

那么就没有办法安全地将其转换为可取消引用的double **p。原因是地址p[2]的内存存储了一个指向double的指针,而地址 arr[2] 的内存存储了一个double(第一个来自 double s 的数组)。

编辑

根据您在评论中表达的"主要问题":双间接寻址在C++中不如在 C 中有用.C 没有引用,所以如果你想让函数提供指针类型的输出参数,它必须采用双指针。例:

void allocate(int style, char **arr)
{
  switch (style) {
    case 0: *arr = malloc(100); break;
    case 1: *arr = malloc(200); break;
    default: *arr = malloc(300); break;
  }
}
int main(void)
{
  char *a;
  allocate(1, &a);  //this way, allocate can modify a
}

在C++中,您可以通过引用传递指针来实现相同的目的:

void allocate(int style, char * &arr)
{
  switch (style) {
    case 0: arr = new char[100]; break;
    case 1: arr = new char[200]; break;
    default: arr = new char[300]; break;
  }
}
int main()
{
  char *a;
  allocate(1, a);  //a is passed by reference, allocate can modify it
}

通常,尽量避开C++中的原始指针并直接使用对象,如果需要动态内存,请尝试使用智能指针。双向指针更是少见。

好吧

double **DPtr;

定义指向双精度指针的指针。这可以有不同的用途,特定于您的问题,它可以用于双精度的 2d 数组。但是请注意,那

double* A = new double[10][10]

确实定义一个长度为 100 双精度的内存块,而不是一个双指针数组,并在每个内存块中定义 10 个双精度。要拥有一个"真正的"2d阵列,您可以做这样的事情

double** A2d = (double*)[10];
for(int i=0; i<10;i++){
    A2d = new double[10]
}

这将创建一个由 10 个数组组成的数组,每个数组的大小为 10。请注意,您可以以相同的方式访问两种类型的 2D 数组,例如 答[1][5]对两者都有效。真正的二维数组将特别有用,二阶数组的大小不同。但总的来说,我建议使用单指针变体。

首先,您可以将其用于 2D 数组(动态分配)。

例如:

double** array;
array = new double*[10];
for(unsigned int i = 0; i < 10; i++){
    array[i] = new double[20];
}

创建一个 10x20 2D 数组,可按如下方式访问

//Classic syntax with subscript operator
double d1 = array[2][4];
//Obfuscate syntax using pointer arithmetics
double d2 = *(*(array+2)+4);

您正在使用指针数组(其本身可以用作数组)。尽管如此,这还是不太实用的,而且是不安全的(在许多情况下,原始指针是不安全的),std::arraystd::vector应该是首选。

但它也可以简单地用作指向指针的指针(它可以比指针更进一步)。

例如:

int var = 10;
int *var_ptr= &var;
int **var_dbl_ptr = &var_ptr;
std::cout << **var_dbl_ptr << std::endl;
//Prints 10

"指向对象的指针"本身就是一个对象,因此本身可以从...一个"指向(指向对象的pojinter)的指针"。

类似地,对象的数组

本身就是一个对象,可以成为"数组(对象的数组)"的一部分

现在,作为"数组的名称"也是"第一个元素的地址",*a 和 a[0](因此 *(a+n) 和 a[n])之间的表达式存在实质上的等价性。

因此,您可以在表达式中使用double** pp,例如pp[3][4] = 3.14;但是数组和指针之间的机制是不同的:

数组看起来像

_ _ _ _ _ 
_ _ _ _ _
_ _ _ _ _ 

显示双向间接寻址

_ -->  _ --> _ _ _ _
       _ --> _ _ _ _ _ _
       _ --> _ _ _ 

在第一种情况下,有一个对象重复 5 次以产生重复 3 次的"宽对象"。

在第二种情况下,有一个"指针到指针"指向"一组三个指针",每个指针指向一组独立的对象(具有独立大小)。

最新更新