Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
数组声明在C++;? 我试图理解C++中声明数组(一个或两个维度)的不同方式以及它们返回的确切内容(指针、指针指向指针等)_C++_Arrays_Pointers_Multidimensional Array - Fatal编程技术网

数组声明在C++;? 我试图理解C++中声明数组(一个或两个维度)的不同方式以及它们返回的确切内容(指针、指针指向指针等)

数组声明在C++;? 我试图理解C++中声明数组(一个或两个维度)的不同方式以及它们返回的确切内容(指针、指针指向指针等),c++,arrays,pointers,multidimensional-array,C++,Arrays,Pointers,Multidimensional Array,以下是一些例子: int A[2][2] = {0,1,2,3}; int A[2][2] = {{0,1},{2,3}}; int **A = new int*[2]; int *A = new int[2][2]; 在每种情况下,A到底是什么?它是指针还是双指针?当我执行A+1时会发生什么?这些都是声明矩阵的有效方法吗 另外,为什么第一个选项不需要第二组大括号来定义“列” 它们将A声明为大小为2的数组,大小为2的数组,大小为int。声明完全相同 int **A = new int*[2];

以下是一些例子:

int A[2][2] = {0,1,2,3};
int A[2][2] = {{0,1},{2,3}};
int **A = new int*[2];
int *A = new int[2][2];
在每种情况下,
A
到底是什么?它是指针还是双指针?当我执行
A+1
时会发生什么?这些都是声明矩阵的有效方法吗

另外,为什么第一个选项不需要第二组大括号来定义“列”

它们将
A
声明为
大小为2的数组,大小为2的数组,大小为int
。声明完全相同

int **A = new int*[2];
这声明了一个指向int的指针的
指针,该指针由两个指针数组初始化。如果要将这两个指针用作二维数组,也应该为其分配内存

int *A = new int[2][2];
这不会编译,因为右边部分的类型是
指向int
大小为2的数组的指针,不能转换为
指向int
的指针

在所有有效情况下,
A+1
&A[1]
相同,这意味着它指向数组的第二个元素,即在
int A[2][2]
的情况下指向两个int的第二个数组,在
int**A
的情况下指向数组中的第二个指针

它们将
A
声明为
大小为2的数组,大小为2的数组,大小为int
。声明完全相同

int **A = new int*[2];
这声明了一个指向int的指针的
指针,该指针由两个指针数组初始化。如果要将这两个指针用作二维数组,也应该为其分配内存

int *A = new int[2][2];
这不会编译,因为右边部分的类型是
指向int
大小为2的数组的指针,不能转换为
指向int
的指针


在所有有效情况下,
A+1
&A[1]
相同,这意味着它指向数组的第二个元素,即在
int A[2][2]
的情况下指向两个int的第二个数组,在
int**A
的情况下指向数组中的第二个指针。

对于数组声明,指定的第一个维度是最外层的维度,即包含其他数组的数组

对于指针声明,每个
*
都会添加另一个间接级别

语法是为C设计的,以使声明模拟使用。C创建者和C++创建者(Bjarne Stroustrup)都把语法描述为失败的实验。主要问题是它没有遵循数学中通常的替换规则

在C++11中,可以使用
std::array
代替方括号声明

您还可以定义类似的
ptr
类型生成器,例如

template< class T >
using ptr = T*;
模板
使用ptr=T*;
然后写

ptr<int> p;
ptr<ptr<int>> q;
ptrp;
ptr-q;

对于数组声明,第一个指定的维度是最外层的维度,即包含其他数组的数组

对于指针声明,每个
*
都会添加另一个间接级别

语法是为C设计的,以使声明模拟使用。C创建者和C++创建者(Bjarne Stroustrup)都把语法描述为失败的实验。主要问题是它没有遵循数学中通常的替换规则

在C++11中,可以使用
std::array
代替方括号声明

您还可以定义类似的
ptr
类型生成器,例如

template< class T >
using ptr = T*;
模板
使用ptr=T*;
然后写

ptr<int> p;
ptr<ptr<int>> q;
ptrp;
ptr-q;

好的,我将尝试向您解释:

  • 这是一个初始化。使用以下值创建二维数组:
    • A[0][0]>0
    • [0][1]->1
    • [1][0]>2
    • A[1][1]>3
  • 这与上面的完全相同,但这里使用大括号。总是这样吗?它更适合阅读
  • int**A表示您有一个指向int指针的指针。当您执行newint*[2]时,您将为整数的2个指针保留内存
  • 这不需要编译

  • 好的,我将尝试向您解释:

  • 这是一个初始化。使用以下值创建二维数组:
    • A[0][0]>0
    • [0][1]->1
    • [1][0]>2
    • A[1][1]>3
  • 这与上面的完全相同,但这里使用大括号。总是这样吗?它更适合阅读
  • int**A表示您有一个指向int指针的指针。当您执行newint*[2]时,您将为整数的2个指针保留内存
  • 这不需要编译

  • 其他答案涵盖了其他声明,但我将解释为什么在前两次初始化中不需要大括号。这两个初始化相同的原因是:

    int A[2][2] = {0,1,2,3};
    int A[2][2] = {{0,1},{2,3}};
    
    是因为它被保险公司覆盖了。在这种情况下,大括号可以“省略”(省略)

    C++标准提供了一个例子,在8.8.1:1:

    [……]

    float y[4][3] = {
      { 1, 3, 5 },
      { 2, 4, 6 },
      { 3, 5, 7 },
    };
    
    [……]

    float y[4][3] = {
      { 1, 3, 5 },
      { 2, 4, 6 },
      { 3, 5, 7 },
    };
    
    在下面的示例中,省略了初始值设定项列表中的大括号; 但是,初始值设定项列表与 上面示例中完全用括号括起来的初始值设定项列表

    float y[4][3] = {
      1, 3, 5, 2, 4, 6, 3, 5, 7
    };
    
    y的初始值设定项以左大括号开始,但y的初始值设定项为[0] 没有,因此使用列表中的三个元素。同样地 接下来的三个分别为y[1]和y[2]


    其他答案涵盖了其他声明,但我将解释为什么在前两次初始化中不需要大括号。这两个初始化相同的原因是:

    int A[2][2] = {0,1,2,3};
    int A[2][2] = {{0,1},{2,3}};
    
    是因为它被保险公司覆盖了。在这种情况下,大括号可以“省略”(省略)

    C++标准提供了一个例子,在8.8.1:1:

    [……]

    float y[4][3] = {
      { 1, 3, 5 },
      { 2, 4, 6 },
      { 3, 5, 7 },
    };
    
    [……]

    float y[4][3] = {
      { 1, 3, 5 },
      { 2, 4, 6 },
      { 3, 5, 7 },
    };
    
    在下面的示例中,省略了初始值设定项列表中的大括号; 然而,我
    int **A = new int*[2];
    
    int *A = new int[2][2];
    
    int *A = new int[4];
    
    int *a = new int(5);
    int *b = new int(6);
    int c[2] = {*a, *b};
    int *d = a;
    
    size_t f0(int* I);
    size_t f1(int I[]);
    size_t f2(int I[2]);
    
    int main(int argc, char** argv)
    {
        // A0, A1, and A2 are local (on the stack) two-by-two integer arrays
        // (they are technically not pointers)
    
        // nested braces not needed because the array dimensions are explicit [2][2]
        int A0[2][2] = {0,1,2,3};
    
        // nested braces needed because the array dimensions are not explicit,
        //so the braces let the compiler deduce that the missing dimension is 2
        int A1[][2] = {{0,1},{2,3}};
    
        // this still works, of course. Very explicit.
        int A2[2][2] = {{0,1},{2,3}};
    
        // A3 is a pointer to an integer pointer. New constructs an array of two
        // integer pointers (on the heap) and returns a pointer to the first one.
        int **A3 = new int*[2];
        // if you wanted to access A3 with a double subscript, you would have to
        // make the 2 int pointers in the array point to something valid as well
        A3[0] = new int[2];
        A3[1] = new int[2];
        A3[0][0] = 7;
    
        // this one doesn't compile because new doesn't return "pointer to int"
        // when it is called like this
        int *A4_1 = new int[2][2];
    
        // this edit of the above works but can be confusing
        int (*A4_2)[2] = new int[2][2];
        // it allocates a two-by-two array of integers and returns a pointer to
        // where the first integer is, however the type of the pointer that it
        // returns is "pointer to integer array"
    
        // now it works like the 2by2 arrays from earlier,
        // but A4_2 is a pointer to the **heap**
        A4_2[0][0] = 6;
        A4_2[0][1] = 7;
        A4_2[1][0] = 8;
        A4_2[1][1] = 9;
    
    
        // looking at the sizes can shed some light on subtle differences here
        // between pointers and arrays
        A0[0][0] = sizeof(A0);        // 16 // typeof(A0) is int[2][2] (2by2 int array, 4 ints total, 16 bytes)
        A0[0][1] = sizeof(A0[0]);     // 8  // typeof(A0[0]) is int[2] (array of 2 ints)
    
        A1[0][0] = sizeof(A1);        // 16 // typeof(A1) is int[2][2]
        A1[0][1] = sizeof(A1[0]);     // 8  // typeof(A1[0]) is int[2]
    
        A2[0][0] = sizeof(A2);        // 16 // typeof(A2) is int[2][2]
        A2[0][1] = sizeof(A2[0]);     // 8  // typeof(A1[0]) is int[2]
    
        A3[0][0] = sizeof(A3);        // 4 // typeof(A3) is int**
        A3[0][1] = sizeof(A3[0]);     // 4 // typeof(A3[0]) is int*
    
        A4_2[0][0] = sizeof(A4_2);    // 4 // typeof(A4_2) is int(*)[2] (pointer to array of 2 ints)
        A4_2[0][1] = sizeof(A4_2[0]); // 8 // typeof(A4_2[0]) is int[2] (the first array of 2 ints)
        A4_2[1][0] = sizeof(A4_2[1]); // 8 // typeof(A4_2[1]) is int[2] (the second array of 2 ints)
        A4_2[1][1] = sizeof(*A4_2);   // 8 // typeof(*A4_2) is int[2] (different way to reference the first array of 2 ints)
    
    // confusion between pointers and arrays often arises from the common practice of
    // allowing arrays to transparently decay (implicitly convert) to pointers
    
        A0[1][0] = f0(A0[0]); // f0 returns 4.
        // Not surprising because declaration of f0 demands int*
    
        A0[1][1] = f1(A0[0]); // f1 returns 4.
        // Still not too surprising because declaration of f1 doesn't
        // explicitly specify array size
    
        A2[1][0] = f2(A2[0]); // f2 returns 4.
        // Much more surprising because declaration of f2 explicitly says
        // it takes "int I[2]"
    
        int B0[25];
        B0[0] = sizeof(B0); // 100 == (sizeof(int)*25)
        B0[1] = f2(B0); // also compiles and returns 4.
        // Don't do this! just be aware that this kind of thing can
        // happen when arrays decay.
    
        return 0;
    }
    
    // these are always returning 4 above because, when compiled,
    // all of these functions actually take int* as an argument
    size_t f0(int* I)
    {
        return sizeof(I);
    }
    
    size_t f1(int I[])
    {
        return sizeof(I);
    }
    
    size_t f2(int I[2])
    {
        return sizeof(I);
    }
    
    // indeed, if I try to overload f0 like this, it will not compile.
    // it will complain that, "function 'size_t f0(int *)' already has a body"
    size_t f0(int I[2])
    {
        return sizeof(I);
    }