[英]for(auto) loop in print function is throwing an error, why?
The for
loop in main
compiles fine but in the print function it doesn't, with the diagnostic main
中的for
循环编译正常,但在打印 function 中它没有,带有诊断
for(auto i:x) cout<<i<<" ";
-----------^std::end
'end' was not declared in this scope; did you mean 'std::end'?
being issued.正在发行。 Here's the full code:
这是完整的代码:
#include <iostream>
void print(int x[],int n)
{
for(auto i:x) std::cout<<i<<" ";
}
int main()
{
int arr[] = {1, 5, 2, 1, 4, 3, 1, 7, 2, 8, 9, 5};
int n = sizeof(arr) / sizeof(int);
for(auto i:arr)
std::cout<<i<<" ";
print(arr, n);
return 0;
}
The issue is that the array arr
decays to a pointer when passed to the function print
.问题是数组
arr
在传递给 function print
时衰减为指针。 The mechanism behind the range-based for
loop is via the use of std::begin
and std::end
.基于范围的
for
循环背后的机制是通过使用std::begin
和std::end
。 That goes some way in explaining the compiler diagnostic: they don't work if applied to pointer types.这在某种程度上解释了编译器诊断:如果应用于指针类型,它们将不起作用。
This pointer decay is the normal behavior when passing array parameters to functions, but is by no means universal.这种指针衰减是将数组参数传递给函数时的正常行为,但绝不是普遍的。 For example,
std::begin
and std::end
obviate this with some template trickery (otherwise they'd be useless for array types), something which you can do too by writing例如,
std::begin
和std::end
通过一些模板技巧来避免这种情况(否则它们对数组类型毫无用处),您也可以通过编写来做到这一点
template<typename T>
void print(T&& x, int n)
{
for(auto i:x) std::cout<<i<<" ";
}
instead.反而。
The plain old datatype int[] has no end-iterator
, if you pass it to a function. In this case you yust pass a pointer to the first item.如果将普通旧数据类型 int[] 传递给 function,则它没有
end-iterator
。在这种情况下,您必须传递指向第一项的指针。 In order to use a range based for loop you have to use a data container, which has a begin- and end-iterator, such as std::vector
为了使用基于范围的 for 循环,您必须使用数据容器,它具有开始和结束迭代器,例如
std::vector
Here is your code in a more C++
way.这是您的代码更多
C++
方式。
#include<vector>
#include<iostream>
void print(const std::vector<int> &x) {
for(auto i:x) {
std::cout<<i<<" ";
}
}
int main() {
const std::vector<int> arr {1, 5, 2, 1, 4, 3, 1, 7, 2, 8, 9, 5};
for(auto i:arr) {
std::cout << i << " ";
}
print(arr);
return 0;
}
@schorsch312's answer is correct, but the suggestion to have the print()
function take an std::vector
is not the "C++ way": Using std::vector
instead of a plain array in your main program is just fine, but when writing a function - I would recommend not to take a type more specific than what you actually need to perform the function's work, and specifically not allocate memory on the heap with a new vector. @schorsch312 的回答是正确的,但是让
print()
function 采用std::vector
的建议不是“C++ 方式”:在主程序中使用std::vector
而不是普通数组就可以了,但是当编写 function - 我建议不要采用比执行函数工作实际需要的类型更具体的类型,特别是不要使用新向量在堆上分配 memory。
For the case of you having a C array in your program, @Bathsheba's suggestion of a print()
is better in my opinion, in that it will allow you to pass the array as-such, and thus iterate over it properly.对于你的程序中有一个 C 数组的情况,我认为 @Bathsheba 的
print()
建议更好,因为它允许你按原样传递数组,从而正确地迭代它。
However - for pedagogical reasons, I would suggest you consider this version print()
:但是 - 出于教学原因,我建议您考虑这个版本
print()
:
template <std::size_t N>
void print(const int (&arr)[N]) {
for(auto i : arr) {
std::cout << i << " ";
}
}
which illustrates how print()
can take an array reference.这说明了
print()
如何获取数组引用。 You need the template when you don't know the array size apriori.当您不知道阵列大小先验时,您需要模板。 (and this also works of course.)
(这当然也有效。)
Alternatively, you could use the standard library algorithm, std::for_each
, like so:或者,您可以使用标准库算法
std::for_each
,如下所示:
#include <vector>
#include <iostream>
#include <algorithm>
int main()
{
int arr[] {1, 5, 2, 1, 4, 3, 1, 7, 2, 8, 9, 5};
for(auto i:arr) {
std::cout << i << ' ';
}
std::cout << '\n';
std::for_each(
std::begin(arr), std::end(arr),
[](auto i) { std::cout << i << ' '; }
);
}
Note that when you use the ranged-for loop, what happens is basically the equivalent of the for_each
invocation, or of a raw for loop over an iterator beginning at std::begin(arr)
and ending at std::end(arr)
.请注意,当您使用 ranged-for 循环时,所发生的基本上等同于
for_each
调用,或者等同于从std::begin(arr)
到std::end(arr)
结束的迭代器上的原始 for 循环.
Yet another alternative - which does not require concerning yourself with iterator pairs - is to have a print()
function taking a span
( What is a "span" and when should I use one? ).还有另一种选择——不需要关心迭代器对——是让
print()
function 取一个span
(什么是“跨度”,我什么时候应该使用一个? )。 Here it makes some sense since a plain C array can be referred to by a span: It has contiguous element storage and a specific length.在这里它是有道理的,因为一个普通的 C 数组可以被一个跨度引用:它有连续的元素存储和特定的长度。 If you were to be using C++20, your span-using print function would look like this:
如果您要使用 C++20,您的 span-using print function 将如下所示:
#include <span>
void print(const std::span<int> &sp) {
for(auto i : sp) {
std::cout << i << ' ';
}
}
and again you don't have to specify the length in your main function. C++14 doesn't have spans in the standard library, but the C++ Guidelines Support Library (see here or here ) has it, as gsl::span
- and it works in C++14.同样,您不必在主 function 中指定长度。C++14 在标准库中没有跨度,但 C++ 指南支持库(请参阅此处或此处)有它,如
gsl::span
- 并且它在 C++14 工作。
Nitpicks:挑剔:
return 0
from main()
- that happens automatically.main()
return 0
- 这会自动发生。#include
directives and the angle-brackets (ie #include <foo>
, not #include <foo>
.#include
指令和尖括号之间使用空格(即#include <foo>
,而不是#include <foo>
。<<
operators.<<
运算符前后使用空格。std::cout << ' '
rather than std::cout << " "
.std::cout << ' '
而不是std::cout << " "
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.