我是C ++的新手,我试图遍历c ++函数中数组的每个元素,但是会出现编译时错误。有人可以解释为什么会这样吗?
这是我的代码:
@ViewChild(ModalDirective) modal: ModalDirective;
showModal() {
this.modal.show();
}
这是错误消息:
#include <iostream>
int getMax(int arr[])
{
int max = arr[0];
for (int x: arr){
if ( x > max ) max = x;
}
return max;
}
int main()
{
int arr[] = {4,2,5,3,6,8,1};
int max = getMax(arr);
std::cout << max << std::endl;
return 0;
}
答案 0 :(得分:6)
您必须通过引用传递数组以保留大小信息:
template <std::size_t N>
int getMax(const int (&arr)[N])
{
int max = arr[0];
for (int x: arr){
if ( x > max ) max = x;
}
return max;
}
否则必须通过指针传递大小。
int getMax(const int *arr, std::size_t size)
{
assert(arr != nullptr);
assert(size != 0);
return *std::max_element(arr, arr + size);
}
使用std::vector
/ std::array
具有更自然的语法。
int getMax(const std::vector<int>& arr)
{
assert(!arr.empty());
#if 1
return *std::max_element(arr.begin(), arr.end());
#else
int max = arr[0];
for (int x: arr){
if ( x > max ) max = x;
}
return max;
#endif
}
int main()
{
const std::vector<int> arr{4,2,5,3,6,8,1};
const int max = getMax(arr);
std::cout << max << std::endl;
}
答案 1 :(得分:3)
问题在于,一旦将数组传递给函数,它就不再是数组,而是指向其第一个元素的指针。
当您拥有指向第一个元素的指针时,您将不再拥有有关它指向的数据的任何信息(类型除外)。更重要的是,您对ranged for
loop所需的“数组”的 end 一无所知。
简单的解决方案是不使用C风格的纯数组,而使用例如std::array
,它将获得有关其大小的信息,并可以在范围for
循环中使用。
有一种方法可以使用传递实际数组(或更确切地说是对它的引用)并获取大小,如the answer from Jarod42中所述。
重要说明:即使使用[]
声明参数(如int arr[]
一样),它也不是数组。如错误消息所示,编译器会将其转换为指针(在您的情况下为int* arr
)。
答案 2 :(得分:0)
问题在于您的函数未使用数组。
int getMax(int arr[]) // <-- arr is not an array
将数组作为C ++函数的参数是不可能的。这没有任何意义,这只是C ++历史的一部分。使用std::vector
代替数组也是一个很好的理由。
实际上arr
是一个指针,您可以在错误消息中看到它
get_max.cpp: In function 'int getMax(int*)':
问题是
for (int x: arr){
如果arr
是指针,则不合法。
您应该做的是将数组的大小传递给函数。像
int getMax(int* arr, size_t size)
{
int max = arr[0];
for (size_t i = 0; i < size; ++i ){
if ( arr[i] > max ) max = arr[i];
}
return max;
}
或者使用std::vector
。
答案 3 :(得分:0)
原始数组作为指针传递,有人说它们在传递给函数时会“衰减”到指针。
int getMax(int arr[])
等同于
int getMax(int* arr)
有些人对单个对象使用后一种语法,前者表示一个函数需要一个数组–仍然只是一个指针(更精确地说:指向数组第一个元素的指针)。
这是原始数组的问题–您不必担心是否使用std::array
(通过const(!)引用传递),但是您可能需要从中创建模板函数才能传递任意长度的数组。如果您需要可变长度的数组(或希望避免使用模板),则可以使用std::vector
。
对于原始数组,您需要将数组长度作为另一个参数传递,然后需要使用经典循环(基于范围的循环不适用于指针):
int getMax(int const arr[], size_t length)
// ^^^^^ you do not intend to modify the array so pass as const!
{
int max = *arr;
++arr;
while(--length) // if you didn't use arr[0] before: length--
{
if(*arr > max)
max = *arr;
}
}
一种变体:向数组传递引用–为了能够使用任意长度,尽管如此,您需要创建以下模板函数:
template <size_t N>
int getMax(int const(&arr)[N]) // ugly syntax, I know...
// again: you do not intend, so pass as const
{
/* now your code works */
}
它是对长度为N的数组的引用,类似地,您可以具有指针:
int(*arr)[N]
如果使用数组的地址,则将得到以下类型:
int a[7];
someFunction(a); // a decays to pointer: int* (unless reference as above used)
someOtherFunction(&a); // a is passed as pointer to array: int(*)[7]
顺便说一句:您已经在重新发明轮子,因为已经有std::max_element
了,尽管您需要将它与迭代器一起使用。指针,尽管完全可以接受,但它也是完全有效的迭代器,对于原始数组,使用最终迭代器有点难看:
int main()
{
int arr[] = {4,2,5,3,6,8,1};
int max = *std::max_element
(
arr, // decays to pointer
sizeof(arr) / sizeof(*arr)
// arr has not yet decayed ... so you need to devide
// to pointer so sizeof is by size of first element
// OK; but it is size in to get the number of elements
// bytes(!)...
);
// ...
最后一个问题:您永远不会检查数组长度实际上是否> 0;如果不是,则访问数组超出范围(未定义的行为!):
int max = arr[0]; // (!)
您可以轻松避免这种情况:
int max = std::numeric_limits<int>::min();
唯一的缺点:您无法将空数组与仅包含最小int值的数组区分开。公认的是,无论如何都不会传递空数组,但是使用std :: vector时,机会通常会更大。但是最后,您实际上是安全的,没有任何成本-好吧,(通常)一次选择另一个分支,并对第一个元素进行一次额外的分配...)。