1

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

double **DPtr; // just for example

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

那么,如果我不能对多维数组使用双重间接,那它有什么用呢?

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

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

4

4 回答 4

5

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

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];

那么就无法安全地将其转换为 dereferencable double **p。原因是地址处的内存p[2]存储指向 的指针double,而地址 arr[2] 处的内存存储 a double(来自 s 数组的double第一个)。

编辑

根据您在评论中表达的“主要问题”:双重间接在 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++ 中的原始指针并直接使用对象,如果需要动态内存,则使用智能指针。双间接指针就更罕见了。

于 2013-09-19T14:56:54.963 回答
2

出色地

double **DPtr;

定义一个指向双精度指针的指针。这可以有不同的用途,具体到您的问题,它可以用于双精度的二维数组。但是请注意,

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

确实定义了一个长度为 100 双精度的内存块,而不是一个双指针数组,并在每个内存块中定义了一个十个双精度数。要拥有一个“真实的”二维数组,您可以执行以下操作

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

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

于 2013-09-19T15:00:52.300 回答
1

“指向对象的指针”本身就是一个对象,因此可以从……“指向(指向对象的指针)的指针”中“指向”自身。

类似地,对象数组本身就是一个对象,可以成为“(对象数组)数组”的一部分

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

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

一个数组看起来像

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

双重间接看起来像

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

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

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

于 2013-09-19T15:08:37.453 回答
1

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

例如:

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);

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

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

例如 :

int var = 10;
int *var_ptr= &var;
int **var_dbl_ptr = &var_ptr;

std::cout << **var_dbl_ptr << std::endl;
//Prints 10
于 2013-09-19T15:04:11.263 回答