您如何理解错误:无法从“int []”转换? 到“int []”

发布于 2024-07-13 02:12:07 字数 245 浏览 9 评论 0原文

编译以下代码时:

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

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

我明白它实际上是在尝试将指针转换为一个不会发生的数组上班。 但是你如何向学习 C++ 的人解释这个错误呢?

When compiling the following code:

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

the VS2005 compiler complains with the error C2440: 'initializing' : cannot convert from 'int []' to 'int []'

I understand that really it's trying to cast a pointer to an array which is not going to work. But how do you explain the error to someone learning C++?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

初心 2024-07-20 02:12:07

假设存在类型和不完整类型:

struct A;

是名为 A 的结构体的不完整类型。 而

struct A { };

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

存在像上面的结构体这样的不完整的类类型。 但也有不完全数组类型:

typedef int A[];

那就是一种不完全数组类型,称为 A。它的大小尚不清楚。 您无法用它创建数组,因为编译器不知道该数组有多大。 但是您可以使用它来创建一个数组,如果您立即初始化它:

A SomeArray = { 1, 2, 3 };

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

Say that there are types and incomplete types:

struct A;

Is an incomplete type of a struct called A. While

struct A { };

Is a complete type of a struct called A. The size of the first is not yet known, while the size of the second is known.

There are incomplete class types like the above struct. But there are also incomplete array types:

typedef int A[];

That is an incomplete array type called A. Its size is not yet known. You cannot create an array out of it, because the compiler does not know how big the array is. But you can use it to create an array, only if you initialize it straight away:

A SomeArray = { 1, 2, 3 };

Now, the compiler knows the array is an int array with 3 elements. If you try to initialize the array with a pointer, the compiler will not be any more clever than before, and refuse, because that won't give it the size of the array to be created.

眼泪也成诗 2024-07-20 02:12:07

为了让错误消息更有帮助,编译器实际上是在混淆事情。 即使 Numbers 参数被声明为数组,C/C++ 实际上不会(不能)传递数组 - Numbers 参数实际上是一个指针。

因此,错误实际上应该是“无法从 'int *' 转换为 'int []'”

但这样就会出现混乱 - “嘿,不涉及 int*在表达中”,有人可能会说。

出于这个原因,最好避免数组参数 - 将它们声明为指针,因为这才是您真正得到的。 对学习 C/C++ 的人的解释应该让他们了解数组参数是虚构的 - 它们实际上是指针。

In trying to make the error message more helpful, the compiler is actually confusing things. Even though the Numbers parameter is declared as an array, C/C++ do not (cannot) actually pass an array - the Numbers parameter is actually a pointer.

So the error really should say "cannot convert from 'int *' to 'int []'"

But then there would be confusion - "hey, there's no int* involved in the expression", someone might say.

For this reason it really is better to avoid array parameters - declare them as pointers, since that's what you're really getting anyway. And the explanation to someone learning C/C++ should educate them on the fact that array parameters are a fiction - they're really pointers.

戒ㄋ 2024-07-20 02:12:07

您需要向您想要帮助的人解释三件事:

  1. 数组不能按值传递给 C++ 中的函数。要做您想做的事情,您需要将数组的开头地址传递给 DoSomething(),以及单独的 int 中的数组大小(嗯,size_t,但我懒得这么说)争论。 您可以使用表达式 &(myArray[0]) 获取某个数组 myArray 的起始地址。 由于这是很常见的事情,C++ 允许您仅使用数组的名称(例如 myArray)来获取其第一个元素的地址。 (这可能有用,也可能令人困惑,具体取决于您看待它的方式。)为了让事情变得更加混乱,C++ 允许您指定数组类型(例如 int Numbers[])作为参数到一个函数,但秘密地,它将该参数视为声明为指针(在本例中为 int *Numbers)——您甚至可以执行 Numbers += 5 > 在 DoSomething() 中使其指向从第六个位置开始的数组!

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

  3. 您无法将一个数组复制到另一个数组中,或初始化一个数组因此,即使参数 Numbers 实际上是一个数组(比如大小为 1000)而不是指针,并且您指定了 SomeArray 的大小> (再次说 1000),行 int SomeArray[1000] = Numbers; 是非法的。


要在 DoSomething() 中执行您想要执行的操作,请首先问自己:

  1. 我需要更改 Numbers 中的任何值吗?
  2. 如果是这样,我是否想阻止调用者看到这些更改?

如果任一问题的答案是“否”,那么您实际上不需要首先复制 Numbers —— 只需按原样使用它,而无需创建单独的 <代码>SomeArray 数组。

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

There are three things you need to explain to the person you're trying to help:

  1. Arrays can't be passed by value to a function in C++. To do what you are trying to do, you need to pass the address of the start of the array to DoSomething(), as well as the size of the array in a separate int (well, size_t, but I wouldn't bother saying that) argument. You can get the address of the start of some array myArray with the expression &(myArray[0]). Since this is such a common thing to want to do, C++ lets you use just the name of the array -- e.g. myArray -- to get the address of its first element. (Which can be helpful or confusing, depending on which way you look at it.) To make things even more confusing, C++ allows you to specify an array type (e.g. int Numbers[]) as a parameter to a function, but secretly it treats that parameter as though it was a declared as a pointer (int *Numbers in this case) -- you can even do Numbers += 5 inside DoSomething() to make it point to an array starting at the sixth position!

  2. When you declare an array variable such as SomeArray in C++, you must either provide an explicit size or an "initialiser list", which is a comma-separated list of values between braces. It's not possible for the compiler to infer the size of the array based on another array that you are trying to initialise it with, because...

  3. You can't copy one array into another, or initialise one array from another in C++. So even if the parameter Numbers was really an array (say of size 1000) and not a pointer, and you specified the size of SomeArray (again as say 1000), the line int SomeArray[1000] = Numbers; would be illegal.


To do what you want to do in DoSomething(), first ask yourself:

  1. Do I need to change any of the values in Numbers?
  2. If so, do I want to prevent the caller from seeing those changes?

If the answer to either question is "No", you don't in fact need to make a copy of Numbers in the first place -- just use it as is, and forget about making a separate SomeArray array.

If the answer to both questions is "Yes", you will need to make a copy of Numbers in SomeArray and work on that instead. In this case, you should really make SomeArray a C++ vector<int> instead of another array, as this really simplifies things. (Explain the benefits of vectors over manual dynamic memory allocation, including the facts that they can be initialised from other arrays or vectors, and they will call element constructors when necessary, unlike a C-style memcpy().)

冷弦 2024-07-20 02:12:07

当我试图解释某件事时,我总是尝试深入到最低的层次,然后从那里开始逐步展开。 这就是我喜欢学习东西的方式,我发现如果你从人们所知道的基础知识开始,然后从那里开始积累,人们会更舒服。

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

编译器正在尝试执行以下操作
作业,因为你写了一个
赋值操作。 在 C++ 中,你
不能直接赋值给数组,
因为它没有内置分配
运算符(任何类型,仅
支持初始化程序和索引
对于数组)。 因为C++支持
类型的重载运算符,
然后编译器寻找重载的
赋值运算符为
“分配给”类型,它采用
“分配自”类型作为其参数。
因为也没有超载
int[] 的运算符,它接受 int[]
作为参数,编译器错误
该行,错误正在告诉你
为什么编译器无法处理该行。

是的,与仅仅谈论有关大小、不完整类型等的知识相比,这可能有点矫枉过正。我意识到它也不完整(例如:没有讨论初始化器分配与正常分配等)。 然而,我的目标通常是让人们能够自己找出下一个答案,为此,你通常需要列出得出答案的思维过程。

When I'm trying to explain something, I always try to go down to the lowest level, and build up from there. That's they way I like to learn things, and I find that people are more comfortable if you start with the basics which they know, and build up from there.

In this case, I'd probably start with something like:

The compiler is trying to do the
assignment, because you wrote an
assignment operation. In C++, you
can't directly assign to an array,
because it has no built-in assignment
operator (of any kind, only
initializer and indexing is supported
for arrays). Because C++ supports
overloaded operators for types, the
compiler then looks for an overloaded
assignment operator for the
"assigned-to" type which takes the
"assigned-from" type as its argument.
Since there's also no overloaded
operator for int[] which takes int[]
as an argument, the compiler errors on
the line, and the errors is telling you
why the compiler can't process the line.

Yes, it's probably overkill vs just saying something about knowledge of size, incomplete types, etc. I realize it's also not complete (eg: no discussion of initializer assignment vs normal assignment, etc.). However, my goal is usually to get people to where they can figure out the next answer themselves, and for that you usually want to lay out the thought process for arriving at the answer.

绝不服输 2024-07-20 02:12:07

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

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

Perhaps your answer could be, "Because the compiler doesn't know how big the array is."

Your example could work if there were explicit array sizes (perhaps with a typedef for clarity), and then you can explain pointers while introducing variable size allocations.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文