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