内部函数的范围错误 我在C++中有一点麻烦。我试图用它来显示和int数组(int[])上的元素,当我在主函数上这样做时,它完全可以正常工作,如: int main(int argc, char const *argv[]) { int v[] = {3, 4, 6, 9, 2, 1}; for (auto a : v) { std::cout << a << " "; } std::cout << std::endl; return 0; }
但当我尝试在函数中使用range for时,事情变得有点奇怪,例如,我对以下代码有一个问题:内部函数的范围错误 我在C++中有一点麻烦。我试图用它来显示和int数组(int[])上的元素,当我在主函数上这样做时,它完全可以正常工作,如: int main(int argc, char const *argv[]) { int v[] = {3, 4, 6, 9, 2, 1}; for (auto a : v) { std::cout << a << " "; } std::cout << std::endl; return 0; },c++,arrays,ranged-loops,C++,Arrays,Ranged Loops,但当我尝试在函数中使用range for时,事情变得有点奇怪,例如,我对以下代码有一个问题: void printList(int *v); int main(int argc, char const *argv[]) { int v[] = {3, 4, 6, 9, 2, 1}; printList(v); return 0; } void printList(int *v) { for (auto a : v) { std::cout << a
void printList(int *v);
int main(int argc, char const *argv[]) {
int v[] = {3, 4, 6, 9, 2, 1};
printList(v);
return 0;
}
void printList(int *v) {
for (auto a : v) {
std::cout << a << " ";
}
std::cout << std::endl;
}
为什么会这样?有没有不使用模板格式的简单解决方案?是否有一种方法可以使用参数作为传递数组和隐式大小信息的方法?对于
循环,这样的使用开始
和结束
成员函数来确定序列的开始和结束位置
例如,std::vector
确实有这些函数,因此支持这种迭代。实际上,指针仅仅是表示内存地址的整数,没有这些函数,因此不可能以这种方式对指针进行迭代(指针本身没有多大意义)
您可以像这样进行迭代:
void printList(int *begin, int *end) {
for(; begin < end; ++begin)
std::cout << *begin;
std::cout << std::endl;
}
void打印列表(int*begin,int*end){
对于(;开始<结束;++开始)
数组和指针之间有很大的区别
您可以使用基于范围的for迭代数组,因为数组的大小在编译时是已知的。但是,您传递给函数的是指向数组第一个元素的指针。在这一步中,大小是未知的,这就是基于范围的for失败的原因
在关于模板的第二个示例中,问题是,您忘记了printList
的定义中的template
,因此您有两个不同的函数,模板化函数和非模板化函数,称为
在这种情况下-我建议使用更现代的std::array
main
中的数组具有已知大小
一旦传递到printList
函数,它就会衰减为指向int
s的指针,因此会出现错误
“我认为这可能发生的原因是,因为我是
数组的指针表示某些信息丢失,但原因是什么
这个信息丢失了,我不知道。”
是的。数组很容易衰减为指针,指针不知道数组长度。从数据类型计算begin()
和end()
需要基于范围的for循环。
我的建议是避免使用C样式的数组,而是使用std::array
:
#include <iostream>
#include <array>
void printList(std::array<int,6> const& v);
int main(int argc, char const *argv[]) {
std::array<int,6> v{{3, 4, 6, 9, 2, 1}};
printList(v);
return 0;
}
void printList(std::array<int,6> const& v) {
for (auto a : v) {
std::cout << a << " ";
}
std::cout << std::endl;
}
#包括
#包括
无效打印列表(标准::数组常量&v);
int main(int argc,char const*argv[]{
std::数组v{{3,4,6,9,2,1};
印刷品清单(五);
返回0;
}
无效打印列表(标准::数组常量&v){
用于(自动a:v){
STD::CUT> P>当将数组传递给函数时,它会衰变为指针,因此它失去了与STD::START和STD::Endo:ToME一起使用的能力。一种现代的方法来使用你想要的是使用STD:::Calpod(如果可能的话,你不应该在C++中使用C样式数组):
#包括
#包括
模板
无效打印列表(常量标准::数组和v)
{
用于(自动a:v){
标准::cout
获取了int[6]
,而int*v
的类型。其类型是int*
。您可以使用指向int的指针访问数组,但它不包含有关该数组大小的信息。
您可以像这样传递数组,但要根据数组的大小来限制自己:
void foo(int (&p)[6])
或制作模板:
template <std::size_t size> void foo( int (&p)[size] )
template <int size>
void printList(int (&v)[size]) {
for (auto& a : v) {
std::cout << a << " ";
}
}
模板void foo(int&p)[size])
如果出于某种原因,您不能使用automic for()循环(例如,为了便于移植到C++11\14支持不可靠的平台),您需要使用std::array\std::vector或pass pointer and size of array您可以将固定大小的数组传递给函数:
void printList(int (&v)[6]) { // pass by reference
for (auto& a : v) { // use reference to avoid making a copy
std::cout << a << " ";
}
}
印刷品:
3 4 6 9 2 1
基于范围的for循环本质上只不过是语法上的糖,即从
for(range\u声明:range\u表达式)loop\u语句(直到C++20)
for(init语句(可选)range\u声明:range\u表达式)loop\u语句
在功能上等同于以下各项:
{
自动范围=范围表达式;
对于(自动开始=开始执行,结束=结束执行;
__开始!=\uuu结束;++\uu开始){
范围\声明=*\开始;
循环语句
}
}
或者,如果您使用c++17或更高版本,它有效地允许使用不同类型的\uu begin
和\uu end
{
init-statement // only since C++20
auto && __range = range_expression ;
auto __begin = begin_expr ;
auto __end = end_expr ;
for ( ; __begin != __end; ++__begin) {
range_declaration = *__begin;
loop_statement
}
}
其中begin_expr
和end_expr
的格式如下
如果range_expression是数组类型的表达式,那么begin_expr是_range,end_expr是(_range+_bound),其中_bound是数组中的元素数(如果数组大小未知或类型不完整,则程序格式不正确)
如果range_expression是一个C类类型的表达式,其成员名为begin和/或end(无论该成员的类型或可访问性如何),则begin_expr是u range.begin(),end_expr是u range.end()
否则,begin_expr是begin(_range),end_expr是end(_range),它们是通过参数相关查找找到的(不执行非ADL查找)
让我们看看这如何适用于您的案例:
在第一种情况下,v
肯定是数组类型的表达式,或者确切地说是类型int(&)[6]
,因此我们使用案例(1),其中\uu-bound=6
等(为了简洁起见,省略完全的扣除替换)
在第二种情况下,当您有一个函数时,v
的类型为int*
,并且由于它不是数组类型,指针也没有成员,因此我们默认使用案例(3),该案例用于确定调用begin(\uu范围)的函数
这不会产生指针类型的结果,因此编译器会抱怨错误:“begin”未在此范围内声明
<
int v[] = {3, 4, 6, 9, 2, 1};
void foo(int (&p)[6])
template <std::size_t size> void foo( int (&p)[size] )
void printList(int (&v)[6]) { // pass by reference
for (auto& a : v) { // use reference to avoid making a copy
std::cout << a << " ";
}
}
template <int size>
void printList(int (&v)[size]) {
for (auto& a : v) {
std::cout << a << " ";
}
}
int main() {
int v[] = {3, 4, 6, 9, 2, 1};
printList(v);
}
3 4 6 9 2 1
{
init-statement // only since C++20
auto && __range = range_expression ;
auto __begin = begin_expr ;
auto __end = end_expr ;
for ( ; __begin != __end; ++__begin) {
range_declaration = *__begin;
loop_statement
}
}
template <std::size_t len>
void printList(int (&v)[len]);
int main(int argc, char const *argv[]) {
int v[] = {3, 4, 6, 9, 2, 1};
printList(v);
return 0;
}
template <std::size_t len>
void printList(int (&v)[len]) {
for (int a : v) {
std::cout << a << " ";
}
std::cout << std::endl;
}