将数组分配给数组

22

所以我在玩弄一些数组,但我无法弄清楚为什么它不起作用。

int numbers[5] = {1, 2, 3};
int values[5] = {0, 0, 0, 0, 0};
values = numbers; 

出现了以下错误:

Error   1   error C2106: '=' : left operand must be l-value c:\users\abc\documents\visual studio 2012\projects\consoleapplication7\consoleapplication7\main.cpp 9   1   ConsoleApplication7

为什么我不能像那样做?这个错误是什么意思?

6个回答

36

由于C++与C向后兼容,数组具有各种丑陋的行为。其中之一是数组不可赋值。请使用std::arraystd::vector

#include <array>
...
std::array<int,5> numbers = {1,2,3};
std::array<int,5> values = {};
values = numbers;
如果出于某种原因必须使用数组,那么您将不得不通过循环或使用循环的函数(比如std::copy)复制元素。
#include <algorithm>
...
int numbers[5] = {1, 2, 3};
int values[5] = {};
std::copy(numbers, numbers + 5, values);

顺便提一下,您可能已经注意到我在初始化 values 数组时的方式有所不同,只提供了一个空的初始化器列表。我依赖于标准中的一个规则,该规则指出,如果您为聚合体(aggregate)提供了一个初始化器列表,无论其多么部分,所有未指定的元素都将使用值初始化。对于整数类型,值初始化意味着将其初始化为零。所以这两个是完全等价的:

int values[5] = {0, 0, 0, 0, 0};
int values[5] = {};

如果数组是二维的,这个代码还能正常工作吗?使用 numbers[5][10] 而不是 numbers[5]。 - tauseef_CuriousGuy

8

在C++中,你不能直接赋值给数组,这很低效但是却是事实。你必须一个一个地复制数组元素。或者你可以使用内置函数memcpystd::copy

或者你可以放弃使用数组,改用std::vector。它们可以被赋值。


4

数组名称是常量不可修改的左值,您不能修改它。

values = numbers; 
// ^
// is array name

阅读编译器错误信息:"error C2106: '=' : 左操作数必须是左值" 左值是可修改的并可以出现在=的左手边。

您可以将数组名称分配给指针,例如:

int* ptr = numbers;

注意:数组名称是常量,但您可以修改其内容,例如value[i] = number[i]0 <= i < 5的有效表达式。

为什么我不能像那样做呢?

基本上,这个限制是由语言强加的。在内部,数组名称用作基地址,并且通过使用基地址进行索引,您可以访问为数组分配的连续内存中的内容。因此,在C/C++中,数组名称将出现在左手边而不是l-value。

1
数组名称是常量而不是左值。指向数组的名称是左值,因为所有引用函数、变量或数据成员的 id 表达式 都是左值 [expr.prim.general]/8。这有点棘手:赋值运算符需要一个可修改的左值,但是这个左值在 C++ 标准中没有定义,只在 C 标准中定义:6.3.2.1/1 "可修改的左值是一个没有数组类型的左值[...]"。因此,数组是一个左值,但不是可修改的左值,因此不能出现在赋值的左侧。 - dyp
@DyP 是的,我明白了,我应该写“数组名称是常量,不可修改的左值”。 - Grijesh Chauhan
@DyP 同样地,consti 是一个左值但不可修改的左值。感谢您的注意,现已更正。 - Grijesh Chauhan

0

values = numbers; 因为numbers和values都是指针。

int numbers[5] = {1, 2, 3};
int values[5] = {0, 0, 0, 0, 0};
for(int i = 0;i < 5; i ++){
    values[i] = numbers[i];
}

1
numbersvalues不是指针,它们是数组。我会预先回应你的异议。数组不是指针(无论是否为const)。数组名也不是指针(无论是否为const)。数组就是数组,而数组名是用于在源代码中引用数组的字符序列。 - Benjamin Lindley

0

std::array 是一个好主意,但这也是可能的:

struct arr { int values[5]; };

struct arr a{{1, 2, 3}};
struct arr b{{}};

a = b;

否则,请使用 std::memcpystd::copy

0

我认为不可分配的原因是C语言想要确保对数组中任何元素的指针几乎总是有效的。

想想允许动态调整大小的向量:在自动调整大小发生后,旧的指针变得无效(非常糟糕)。

附注:对于向量的设计哲学,以下代码块可以很好地工作。

vector<int> v = {1, 5, 16, 8};
vector<int> v_2 = {7, 5, 16, 8};
v_2 = v;

确保数组中任何元素的指针始终有效,这在此处并不适用,因为他试图分配相同大小的数组。 - Parker Coates

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接