你如何理解错误:无法从'int []'转换为'int []'

时间:2009-02-11 06:57:31

标签: c++ arrays visual-studio-2005 pointers error-code

编译以下代码时:

void DoSomething(int Numbers[])
{
    int SomeArray[] = Numbers;
}

VS2005编译器抱怨错误C2440:'初始化':无法从'int []'转换为'int []'

我知道它确实在尝试将指针强制转换为不起作用的数组。但是,如何向学习C ++的人解释错误?

5 个答案:

答案 0 :(得分:12)

说有类型和不完整的类型:

struct A;

是一个名为A.的结构的不完整类型。

struct A { };

是一个名为A的结构的完整类型。第一个的大小尚不清楚,而第二个的大小是已知的。

有不完整的类类型,如上面的结构。但是也存在不完整的数组类型:

typedef int A[];

这是一个名为A的不完整数组类型。它的大小尚不清楚。你不能用它创建一个数组,因为编译器不知道数组有多大。但是你可以使用来创建一个数组,只有 才能立即初始化它:

A SomeArray = { 1, 2, 3 };

现在,编译器知道数组是一个包含3个元素的int数组。如果您尝试使用指针初始化数组,编译器将不再比以前更聪明,并且拒绝,因为这不会给它创建要创建的数组的大小。

答案 1 :(得分:8)

在尝试使错误消息更有用时,编译器实际上是混乱的。即使Numbers参数声明为数组,C / C ++也不会(不能)实际传递数组 - Numbers参数实际上是指针。

所以错误确实应该说"cannot convert from 'int *' to 'int []'"

但是那会有混乱 - “嘿,表达中没有int*参与”,有人可能会说。

由于这个原因,最好避免使用数组参数 - 将它们声明为指针,因为这是你真正得到的。对学习C / C ++的人的解释应该教育他们关于数组参数是虚构的事实 - 他们真的是指针。

答案 2 :(得分:5)

您需要向您尝试提供帮助的人解释三件事:

  1. 数组不能通过值传递给C ++中的函数。要执行您要执行的操作,您需要将数组开头的地址传递给{ {1}},以及单独的DoSomething()(嗯,int中的数组大小,但我不打算说)参数。您可以使用表达式size_t获取某个数组myArray的开头地址。由于这是一个很常见的事情,C ++允许你只使用数组的名称 - 例如&(myArray[0]) - 获取其第一个元素的地址。 (这可能会有所帮助或混淆,具体取决于您查看它的方式。)为了使事情更加混乱,C ++允许您指定一个数组类型(例如myArray)作为函数的参数,但是秘密地它将该参数视为声明为指针(在这种情况下为int Numbers[]) - 您甚至可以在int *NumbersNumbers += 5使其指向从...开始的数组第六名!

  2. 在C ++中声明数组变量(例如DoSomething())时,必须提供显式大小或“初始化列表”,这是逗号分隔的列表大括号之间的值。编译器无法根据您尝试初始化的另一个数组来推断数组的大小,因为......

  3. 您不能将一个数组复制到另一个数组中,或者在C ++中从另一个数组初始化一个数组。所以即使参数SomeArray实际上是一个数组(比如大小) 1000)而不是指针,并且您指定了Numbers的大小(再次说1000),行SomeArray将是非法的。


  4. 要在int SomeArray[1000] = Numbers;做你想做的事,先问自己:

    1. 我是否需要更改DoSomething()中的任何值?
    2. 如果是,我是否要阻止调用者看到这些更改?
    3. 如果对这两个问题的回答都是“否”,那么您实际上并不需要首先复制Numbers - 只是按原样使用它,而忘记单独生成{ {1}}数组。

      如果这两个问题的答案都是“是”,则您需要在Numbers中复制SomeArray并对其进行处理。在这种情况下,你应该真正使Numbers成为C ++ SomeArray而不是另一个数组,因为这真的简化了事情。 (解释向量优于手动动态内存分配的好处,包括它们可以从其他数组或向量初始化的事实,并且它们将在必要时调用元素构造函数,这与C风格{{1 }}。)

答案 3 :(得分:4)

当我试图解释一些事情时,我总是试着降到最低级别,并从那里开始建立。这就是我喜欢学习的方式,我发现如果你从他们所知道的基础开始,并从那里建立起来,人们就会感到更舒服。

在这种情况下,我可能会从以下内容开始:

  

编译器正在尝试执行此操作   任务,因为你写了一个   分配操作。在C ++中,你   无法直接分配给数组,   因为它没有内置的任务   运营商(任何类型,仅限   支持初始化和索引   对于数组)。因为C ++支持   重载运算符的类型,   然后编译器查找重载   赋值运算符   “分配给”类型   “assigned-from”类型作为其参数。   因为也没有超载   int []的运算符,它接受int []   作为参数,编译器错误   这条线,错误告诉你   为什么编译器无法处理该行。

是的,这可能是过度杀戮而只是说一些关于大小,不完整类型等的知识。我意识到它也不完整(例如:没有初始化者分配与正常分配的讨论等)。然而,我的目标通常是让人们到达他们自己能够找到下一个答案的地方,为此你通常想要制定思考过程以获得答案。

答案 4 :(得分:3)

也许你的回答可能是,“因为编译器不知道数组有多大。”

如果存在明确的数组大小(为清晰起见可能使用typedef),您的示例可以工作,然后您可以在引入可变大小分配时解释指针。