定理说我们不能将一个数组初始化为另一个数组的副本。但是我们可以将指针初始化为指向另一个数组的第一个元素的指针的副本:
int a[] = {0, 1, 2};
int a2[] = a; //error
int *a3 = a; //OK
为什么int a2[] = a;
是错误?
定理说我们不能将一个数组初始化为另一个数组的副本。但是我们可以将指针初始化为指向另一个数组的第一个元素的指针的副本:
int a[] = {0, 1, 2};
int a2[] = a; //error
int *a3 = a; //OK
为什么int a2[] = a;
是错误?
数组不能在 C++ 中分配给另一个数组对象或从另一个数组对象初始化,因为它们不能在 C 中,并且由于不再真正相关的历史原因,它们不能在 C 中。
int a[] = {0}; int b[] = {0}; a = b;
在非常早期的 proto-C 中,是否应该将数组的内容复制b
到a
或重新放置a
要引用的名称,会有一些混淆b
。与初始化类似,是否a
应该是副本b
或别名。这种模糊性已经存在了 40 年:很快就很清楚,如果允许它,那么C(和 C++)中的合理含义就是它应该复制,但 C 中的数组从未被制成“正确”的值类型。
没有技术原因不可能,例如,您可以分配具有数组作为数据成员的结构类型。该标准根本没有将您的代码定义为正确的 C++。
指针的行为与此没有直接关系。初始化指针(指向数组的第一个元素)与初始化数组及其内容是不同的操作,并且该语言允许在 RHS 上进行不同的操作。
数组不是指针,所以你不能指望像指针一样使用它们而不会遇到麻烦。访问https://blogs.oracle.com/ksplice/entry/the_ksplice_pointer_challenge,参加一项有助于您了解差异的活动。
如果将数组包装在结构中,则可以将数组初始化为另一个数组的副本。
struct myarray {
int a[3];
};
如果你的编译器允许 GNU C++ 风格的指定初始化器:
myarray a = {a: {0, 1, 2}};
这会复制结构,包括 a 的数组到 a2 的数组。
myarray a2 = a;
数组将位于内存中的不同位置:
bool is_different_array = a2.a != a.a; // true
如果你这样做
int *a3 = a;
你不复制值,只是内存地址,称为指针
如果您不想复制数组的值,则必须定义一个复制构造函数。
让我们以不同的方式来看待它。数组适用于 C/C++ 中的静态分配。所以我们必须确保编译器能够在编译时自己计算出数组的大小,这是数组的强制性条件,因为有很多该死的原因。因此,每当编译器遇到“[]”符号时,它就希望可以从代码本身中计算出内存大小(需要在运行时分配)。
当我们在 C/C++ 中定义一个数组时,会分配数组的内存(当我说数组时,我指的是要存储数组元素的单元格)。现在当你说喜欢
int a[] = {3,4,5,6};
它将分配一些内存,例如 16 个字节用于 4 个元素,这可以由编译器在编译时计算出来。
现在当你说
int a2[] = a;
编译器看到数组符号“[]”,但无法确定需要为数组单元分配多少内存,这会给您一个错误。
当我们谈论一个数组时,它总是关于由一个常量指针指向的被取消引用的单元格,而当我们谈论一个指针时,它可以不引用任何东西而存在,这就是所谓的悬空指针。希望能帮助到你。
可以将一个数组分配给另一个数组——但只能通过将第一个数组的基础数据复制到第二个数组(例如,使用循环)。您问题中的代码行:
int *a3 = a;
只是将调用的指针分配为指向a3
数组的第一个元素的地址a
,但它不会更改这两个变量引用的基础数据(在本例中为整数)。
此外,请查看此内容以了解数组和指针之间的关系。
数组不仅仅是一个指针,在您的示例中,该数组a[]
表示已在内存中保留了 3 个整数大小的连续内存地址。如果您要尝试“复制”该数组,它还必须保留 3 个整数大小的连续内存地址并复制0 1 2
到它们。原语的赋值运算符不会被期望做这么多的工作。
但是,当您创建一个指针时,您只是在命名a[]
.
当您要声明将分配到堆栈上的数组时,编译器需要知道元素的数量,这就是您必须声明的原因:
int a[] = {x,y,etc..};
或者
int a[NUMELEMENTS];
虽然可以接受指向已经存在的数组的指针,但不能从指向已经存在的数组的指针创建新的堆栈数组,这int a2[]= a;
是试图做的事情。编译器不知道要为 a2 分配多少元素。
通常,将一个数组复制到另一个数组的最佳方法是使用std::copy
.