对于循环函数参数在C++中的奇数
For loop over function parameters oddity in C++
在我当前的项目中,我偶然发现了一个奇怪的现象,嵌套的for循环只会执行一次内部循环,然后简单地停止。即使仔细检查了所有涉及的变量,外部for循环仍然无缘无故地终止。使这种结构与我的程序中包含的其他 for 循环唯一不同的是,计数器变量作为参数传递给包含循环的函数,并且从未复制到任何地方。
所以我决定测试是否可以重现该问题:
#include <stdio.h>
void someFunction(int x, int y, int width, int length)
{
int endX = x+width;
int endY = y+length;
printf("x will not exceed: %in", endX);
printf("y will not exceed: %in", endY);
for(; x < endX; x++)
{
for(; y < endY; y++)
{
printf("(%i, %i)n", x, y);
}
}
}
int main(int argc, const char *argv[])
{
someFunction(1, 1, 5, 5);
return 0;
}
但是,在执行时,应用程序的输出与直观的预期不同:
x will not exceed: 6
y will not exceed: 6
(1, 1)
(1, 2)
(1, 3)
(1, 4)
(1, 5)
切换 x 和 y 时的行为类似,但 y 变量永远不会递增。只需声明一个新变量作为每个循环的计数器即可解决此问题。
但为什么会这样呢?是否因特定原因而不允许?编译器是否禁用了某些参数的修改,如果是,为什么它适用于一个变量而不是另一个变量?
提供的源代码是使用 GCC/G++ 4.5.3 编译的,没有任何特殊的优化标志。
y
永远不会在x
循环中重置,因此一旦它在第一次传递时越界,它就会永远越界。
由于x
和y
也存在于循环之外,并且由于循环没有设置其初始值,因此即使重用它们,它们也会保留最后一个值。这特别是关于您的y
,在 y 循环退出后不会倒回到初始值。
若要避免此类问题,请避免使用循环外部的变量作为索引。
void someFunction(const int x, const int y, const int width, const int length)
{
int endX = x+width;
int endY = y+length;
printf("x will not exceed: %in", endX);
printf("y will not exceed: %in", endY);
for(int ix=x; ix < endX; ++ix)
{
for(int iy=0; iy < endY; ++iy)
{
printf("(%i, %i)n", ix, iy);
}
}
}
HEre,通过制作参数 const,我们确保我们不会碰到它们,即使是错误地。然后我们使用循环本地的 ix 和 iy 来处理迭代。
此外,除非出于其他原因必须这样做,否则请避免使用后缀增量,并使用前缀。在使用整数之前,这不是一个很大的变化,但更复杂的变量可以有所作为。
如果你避免像C程序员一样编码,这也是一个好主意(因为你把问题标记为C++
而不是C
)。
惯用语C++等价物是这样的:
#include <iostream>
void someFunction(const int& x, const int& y, const int& width, const int& length)
{
const int endX = x+width;
const int endY = y+length;
std::cout << "x will not exceed: " << endX << std::endl;
std::cout << "y will not exceed: " << endY << std::endl;
for(int ix=x; ix < endX; ++ix)
{
for(int iy=y; iy < endY; ++iy)
{
std::cout << '('<<ix<<", "<<iy<<')'<< std::endl;
}
}
}
int main()
{
someFunction(1, 1, 5, 5);
return 0;
}
相关文章:
- 如何反转整数参数包
- 使用C++库在Android项目中修改gradle中的cmake参数,用于插入指令的测试
- 如何使用默认参数等选择模板专业化
- 模板参数替换失败,并且未完成隐式转换
- 具有默认模板参数的多态类的模板推导失败
- lambda参数转换为constexpr技巧,然后获取带链接的数组
- 将数组作为参数传递给函数安全吗?作为第三方职能部门,可以探索他们想要的之外的其他元素
- 函数调用中参数的顺序重要吗
- 部分定义/别名模板模板参数
- 模板-模板参数推导:三个不同的编译器三种不同的行为
- 使用不带参数的函数访问结构元素
- 基于另一个成员参数将函数调用从类传递给它的一个成员
- 如何在OMNET++中指定与命令行参数组合的输出文件名
- 如何使用Luacneneneba API正确读取字符串和表参数
- 在派生函数中指定void*参数
- 视图中的参数推导失败:take_while
- static_assert在宏中,但也可以扩展到可以用作函数参数的东西
- 使用指向成员的指针将成员函数作为参数传递
- 没有名称的C++模板参数
- 如何将enable-if与模板参数和参数包一起使用