数组声明在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);
}