所以我一直试图更多地理解指针,我遇到了这个:
double **DPtr; // just for example
我已经读过它可以用来指向一个多维数组,但是在我使用单个间接符号(*
)之前我无法让它工作。
那么,如果我不能对多维数组使用双重间接,那它有什么用呢?
我试图找到答案,但我没有运气。
提前感谢您提供的任何信息!:)
所以我一直试图更多地理解指针,我遇到了这个:
double **DPtr; // just for example
我已经读过它可以用来指向一个多维数组,但是在我使用单个间接符号(*
)之前我无法让它工作。
那么,如果我不能对多维数组使用双重间接,那它有什么用呢?
我试图找到答案,但我没有运气。
提前感谢您提供的任何信息!:)
你的问题不太清楚。您可以使用 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++ 中的原始指针并直接使用对象,如果需要动态内存,则使用智能指针。双间接指针就更罕见了。
出色地
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] 对两者都有效。真正的二维数组会特别有用,二阶数组的大小不同。但总的来说,我建议使用单指针变体。
“指向对象的指针”本身就是一个对象,因此可以从……“指向(指向对象的指针)的指针”中“指向”自身。
类似地,对象数组本身就是一个对象,可以成为“(对象数组)数组”的一部分
现在,作为“数组的名称”也是“第一个元素的地址”,*a 和 a[0](因此 *(a+n) 和 a[n])之间的表达式实质上是等价的.
因此,您可以double** pp
使用类似的表达式,pp[3][4] = 3.14;
但数组和指针之间的机制不同:
一个数组看起来像
_ _ _ _ _
_ _ _ _ _
_ _ _ _ _
双重间接看起来像
_ --> _ --> _ _ _ _
_ --> _ _ _ _ _ _
_ --> _ _ _
在第一种情况下,有一个对象重复 5 次以产生一个重复 3 次的“宽对象”。
在第二种情况下,有一个“指针指向指针”指向一个“三个指针组”,每个指针指向一组独立的对象(具有独立的大小)。
首先,您可以将其用于二维数组(动态分配)。
例如:
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