为什么a[]和*a的行为不同

Why do a[] and *a behave differently?

本文关键字:为什么      更新时间:2023-10-16

我认为a[]*a是一样的,因为它们像指针一样工作。然而,我在以下代码中遇到了一些意想不到的东西:

#include <iostream>
using namespace std;
class F {
public:
bool a[];
F();
};
F::F() {
*a = new bool[5];
a[2] = true;
}
int main() {
F obj;
if(obj.a[2])
cout << '?';
return 0;
}

这段代码打印?,但我不明白它是如何工作的。何时:

*a = new bool[5];

改为:

a = new bool[5];

编译器报告:

F:main.cpp|11|error: incompatible types in assignment of 'bool*' to 'bool [0]'|

我觉得这种行为很奇怪,所以我一直在玩这个代码。当我将a的类型从bool更改为int时,编译器总是报告错误

F:main.cpp|11|error: invalid conversion from 'int*' to 'int' [-fpermissive]|

为什么这样工作

我认为a[]*a是一样的,因为它们的工作方式类似于指针。

让我们谈谈这段声明:

int a[4] = { 1, 2, 3, 5 };
int *b = NULL;

这就是它们在可执行文件中进入内存的方式:

+----+----+----+----+
a: |  1 |  2 |  3 |  5 |        <-- 4 integers
+----+----+----+----+
+----------+
b: |   NULL   |                   <-- 1 pointer that points to nowhere
+----------+

正如您所看到的,它们不是一回事。

b = new int[4];之后会发生什么

b的新内存布局是这样的:

+----------+
b: | 0xacf3de |               <-- 1 pointer that points to a block of 4 integers
+----------+
Somewhere else in memory (at address 0xacf3de)...
+----+----+----+----+
0xacf3de: |  ? |  ? |  ? |  ? |         <-- 4 integers
+----+----+----+----+

但是等等,有人告诉我数组的工作原理就像指针

不,那不是真的。数组不像指针那样工作。

数组名称(a,f.e.)可以用作其在内存中的地址(实际上是其第一个元素的地址)的快捷方式。以下符号是等效的:

a
&a
&a[0]

所有这些的值都是存储器中存储a的第一个元素(上面例子中的1)的地址。

a[0]int&a[0]int *。这是完整的表格。另外两个是语言提供的快捷方式,目的是使代码更容易阅读和理解。

指针的情况不同

b是存储在b变量中的值(在上面的例子中是NULL0xacf3de。它是类型为int *的值——存储int的存储器中的地址。&b是存储b的存储器中(的值)的地址。其类型为int **——指向指向int的指针的指针;或"存储器中存储int地址的地址"。

但是等等,在某些情况下它们可以被替换

在某种程度上,指针和数组是可以互换的。正如您在上面看到的,有一种常见的数据类型:int *。它是b的类型(存储int的地址),也是&a[0]的类型(也是int的地址)。

这意味着,在可以使用b的情况下,可以改用a(&a[0]的缩写),反之亦然。

此外,在可以使用*b的情况下,可以替代地使用*a。它是*&a[0]的缩写,意思是"存储在a[0]地址(&)的值(*)",事实上,它与a[0]相同。

但是,在可以使用&b的情况下,不能使用&a;请记住,&a&a[0]相同,其类型为int *(但&b的类型为int **)。

行:

*a = new bool[5];

相当于:

a[0] = new bool[5];

您不是在初始化您的数组,而是分配一个bool数组,然后将其隐式转换为bool,以分配给a[0]:值应该是true,因为new返回的指针应该与0不同。这种隐式转换不适用于ints:这就是为什么在更改a的类型时会出现错误。


现在,考虑这一行:

a = new bool[5];

在这里,您试图将动态分配的数组分配给a,换句话说,将指向数组bool*的指针分配给静态数组bool[0]:正如编译器所说,类型是不兼容的。静态数组a[]可以用作指针,例如在以下代码中:

int foo(bool* a) { /* ... */ }
bool my_array[5];
foo(my_array);

但是指针不能像你尝试的那样转换成静态数组

new Type[x]返回的值的类型是Type *,即类型的指针

examle:所以正确的语法是bool a;

*a = new bool[x];

所以像那样做是错误的

a=new bool[x]语法错误,因为将指针分配给正常可变无效

有关更多详细信息,请参阅