C ++:传递数组是否与指向数组的指针相同?

时间:2013-07-26 19:54:59

标签: c++ pointers

首先我猜想k1的值不会在主空间中。但后来我意识到数组是一个指针,所以有什么区别吗?我认为这是相同的,但也许任何人都可以找到一些其他的技术差异。也许更快地传递指针?

#include <iostream>

using namespace std;

void g(double [],int );
void f(double* [],int );

int main()
{

    int n = 10;
    double *k1, *k2;

    k1 = new double[n];
    k2 = new double[n];

    g(k1,n);
    f(&k2,n);

    for(int i = 0;i <n;i++)
    {
        cout << k1[i]<< " ";
        cout << k2[i] << endl;
    }

    delete [] k1;
    delete [] k2;

    return 0;
}


void g(double h[],int n)
{
     for(int i = 0;i <n;i++)
        h[i]=i;
}

void f(double* h[],int n)
{
     for(int i = 0;i <n;i++)
        (*h)[i]=i;
}

6 个答案:

答案 0 :(得分:7)

首先,数组不是指针。这是10个双打的数组:

double a[10];

这是一个指向double的指针:

double *p;

这是一个指向10个双精度数组的指针:

double (*pa)[10];

这是一系列指向双打的指针:

double *pa[10];

当声明为函数参数时,数组和指针只是相同的。但是数组可以转换(衰减)成指向数组的第一个元素的指针:

double a[10];
double *p = a;
double *q = &a[0]; //same as p

在您的示例代码中:

double *x = new double[10];

您正在创建一个包含10个双打的动态数组,并获取指向该数组的第一个元素的指针。您还可以创建一个新数组并获取指向数组的指针:

double (*x)[10] = new double (*)[10];

但这种奇怪语法的表现很少有用。

关于函数,这是一个带有双精度数组的函数:

void g1(double h[], int n);

这是一个函数,它指向一个包含10个双精度数组的数组:

void g2(double (*h)[10]);

在指向数组的指针中,您需要指定数组的大小,因为您无法创建指向未知大小数组的指针。

这就是为什么数组实际上作为指针传递给函数的原因。但是指向数组的第一个成员的指针,而不是指向数组本身的指针。所以第一个函数实际上与这个函数相同:

void g1(double *h, int n);

由于您只将指针传递给数组的第一个成员(指向double的指针),因此您还需要在附加参数中指定数组的大小。优点是您可以传递任何大小的数组。甚至是阵列的拼接:

double x[20];
g1(x + 10, 5); //pass x[10..15]

关于哪一个更快,它们都是相同的,它们实际上是指向相同内存地址的指针。请注意,如果数组是结构的一部分,则只通过副本传递,并且结构按值传递。

我的建议是:如果你使用C棒到惯用的C,必要时使用指向数组第一个成员的指针,并尽可能避免使用指针到数组的语法。如果使用C ++,则使用容器,迭代器和范围。

答案 1 :(得分:3)

void f(double* h[],int n)

不接受指向数组的指针。你已声明它接受一个指针数组。

它工作的唯一原因是声明为数组的函数参数被静默地转换为指针,因此它等同于:

void f(double** h,int n)

这毕竟是你想要的。

这个(被g ++拒绝)代码将使用指向数组的指针:

void f(double (*h)[],int n)

答案 2 :(得分:2)

有了这个声明:

void f(double* [],int );

您说,作为第一个参数,您正在使用指向double的指针数组。

当您使用(*h)取消引用该参数(其被视为指向指针的指针)时,您实际上会获得该数组的第一个位置的地址。

答案 3 :(得分:1)

void g(double h[],int n);

在该功能中,您在技术上传递指针。

void f(double* h[],int n);

但是在这一个中,你传递一个指向数组的指针,该数组解析为指向指针,因为它是一个函数参数*。

*感谢Ben Voigt

答案 4 :(得分:1)

即使您通过指针传递了值,它指向的内存仍然可以通过函数进行更改。

答案 5 :(得分:0)

许多程序员都有一个关于编译器如何工作的心理模型,其中包括“数组只是一个指针”。这个模型不正确。

 typedef int[10] Array;
 typedef Array * PointerToArray;
 typedef int * Pointer;

 Array a = {0,1,2,3,4,5,6,7,8,9};
 PointerToArray pa;
 Pointer pint = a;   // the compiler casts this automatically to a different type.

此时pint和pa具有相同的二进制值,但pa [1]和a [1]不引用内存中的相同位置。了解原因非常重要。