C++ 重复一段代码固定的次数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16268863/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Repeat a block of code a fixed number of times
提问by Serdnad
I'm trying to repeat a block of code, without using a condition, yet still only repeating it a specific number of times.
我试图在不使用条件的情况下重复一段代码,但仍然只重复特定的次数。
Basically, something like this:
基本上,是这样的:
repeat(50)
{
//Do stuff here.
}
Is there a way to do this? Other than copying and pasting 50 times?
有没有办法做到这一点?除了复制粘贴50次?
I'm doing this because I figured if I know how many times I want to repeat something, it'd be quicker than checking a condition every time. Is that accurate? Or would I still be checking how many times it's been repeated?
我这样做是因为我想如果我知道我想重复多少次的话,它会比每次都检查一个条件要快。那是准确的吗?或者我仍然会检查它重复了多少次?
Basically, is it any faster at all?
基本上,它会更快吗?
回答by phonetagger
Your attempts to optimize the loop by using some construct (incl. manually cutting & pasting the code) to optimize the loop's execution speed are ill-advised. Don't do it; it would probably "un-optimize" the execution speed instead.
您尝试通过使用某些构造(包括手动剪切和粘贴代码)来优化循环的执行速度来优化循环是不明智的。不要这样做;它可能会“取消优化”执行速度。
In any C++ implementation I've ever encountered (MSVC 6.0, 2003, 2005, 2010, GCC various versions, Diab various versions), there is absolutely zero, sorry I didn't stress that enough, ZERO, time involved with allocating a loop counting variable, assuming any other variables were allocated for the function in which the loop counting variable is allocated. For a simple loop that makes no function calls, the loop counting variable may never even make it out to memory; it may be held entirely in a single CPU register for its entire lifetime. Even if it is stored in memory, it would be on the runtime stack, and space for it (and any other local variables) would be claimed all at once in a single operation, which takes no more or less time depending on the number of variables allocated on the stack. Local variables like your loop counter variable are allocated on the stack, and stack allocations are CHEAP CHEAP CHEAP, as opposed to heap allocations.
在我遇到的任何 C++ 实现中(MSVC 6.0、2003、2005、2010、GCC 各种版本、Diab 各种版本),绝对为零,抱歉我没有强调足够,零,分配循环所需的时间计数变量,假设为分配循环计数变量的函数分配了任何其他变量。对于不进行函数调用的简单循环,循环计数变量甚至可能永远不会进入内存;它可以在其整个生命周期内完全保存在单个 CPU 寄存器中。即使它存储在内存中,它也会在运行时堆栈上,并且它(以及任何其他局部变量)的空间将在单个操作中一次全部占用,这取决于数量的多少栈上分配的变量。
Example loop counter variable allocation on the stack:
堆栈上的示例循环计数器变量分配:
for (int i=0; i<50; ++i) {
....
}
Another example loop counter variable allocation on the stack:
堆栈上的另一个循环计数器变量分配示例:
int i = 0;
for (; i<50; ++i) {
....
}
Example loop counter variable allocated on the heap (don't do this; it's stupid):
在堆上分配的示例循环计数器变量(不要这样做;这很愚蠢):
int* ip = new int;
for (*ip=0; *ip<50; ++(*ip)) {
....
}
delete ip;
Now to address the issue of attempting to optimize your loop by manually copying & pasting instead of using a loop & counter:
现在要解决尝试通过手动复制和粘贴而不是使用循环和计数器来优化循环的问题:
What you're considering doing is a manual form of loop unrolling. Loop unrolling is an optimization that compilers sometimes use for reducing the overhead involved in a loop. Compilers can do it only if the number of iterations of the loop can be known at compile time (i.e. the number of iterations is a constant, even if the constant involves computation based on other constants). In some cases, the compiler may determine that it is worthwhile to unroll the loop, but often it won't unroll it completely. For instance, in your example, the compiler may determine that it would be a speed advantage to unroll the loop from 50 iterations out to only 10 iterations with 5 copies of the loop body. The loop variable would still be there, but instead of doing 50 comparisons of the loop counter, now the code only has to do the comparison 10 times. It's a tradeoff, because the 5 copies of the loop body eat up 5 times as much space in the cache, which means that loading those extra copies of the same instructions forces the cache to evict (throw out) that many instructions that are already in the cache and which you might have wanted to stay in the cache. Also, loading those 4 extra copies of the loop body instructions from main memory takes much, much longer than simply grabbing the already-loaded instructions from the cache in the case where the loop isn't unrolled at all.
您正在考虑做的是一种手动形式的循环展开。循环展开是一种优化,编译器有时会使用它来减少循环中涉及的开销。只有在编译时可以知道循环的迭代次数(即迭代次数是一个常数,即使该常数涉及基于其他常数的计算),编译器才能这样做。在某些情况下,编译器可能会确定展开循环是值得的,但通常不会完全展开循环。例如,在您的示例中,编译器可能会确定将循环从 50 次迭代展开到仅具有 5 个循环体副本的 10 次迭代将具有速度优势。循环变量仍然存在,但不再对循环计数器进行 50 次比较,现在代码只需进行 10 次比较。这是一种权衡,因为循环体的 5 个副本占用了缓存中 5 倍的空间,这意味着加载相同指令的那些额外副本会强制缓存驱逐(抛出)已经存在的许多指令缓存以及您可能希望保留在缓存中的内容。此外,在循环根本没有展开的情况下,从主内存加载这 4 个额外的循环体指令副本比简单地从缓存中抓取已经加载的指令要花费更多、更长的时间。这意味着加载相同指令的那些额外副本会强制缓存驱逐(丢弃)已经在缓存中并且您可能希望保留在缓存中的许多指令。此外,在循环根本没有展开的情况下,从主内存加载这 4 个额外的循环体指令副本比简单地从缓存中抓取已经加载的指令要花费更多、更长的时间。这意味着加载相同指令的那些额外副本会强制缓存驱逐(丢弃)已经在缓存中并且您可能希望保留在缓存中的许多指令。此外,在循环根本没有展开的情况下,从主内存加载循环体指令的这 4 个额外副本比简单地从缓存中抓取已经加载的指令要花费更长的时间。
So all in all, it's often more advantageous to just use only one copy of the loop body and go ahead and leave the loop logic in place. (I.e. don't do any loop unrolling at all.)
所以总而言之,只使用循环体的一个副本并继续保留循环逻辑通常更有利。(即根本不进行任何循环展开。)
回答by Mats Petersson
It would be entirely possible to have a repeat(x)
as part of the language, but there isn't such a thing for some reason - the design of C and C++ does somewhat follow what the processors can do, and I'm not familiar with a single processor (I've worked with about 10 different processor architectures) that can do a "loop this many times" without some sort of "check if we reached the number".
完全有可能将 arepeat(x)
作为语言的一部分,但由于某种原因没有这样的事情 - C 和 C++ 的设计确实在某种程度上遵循处理器可以做的事情,而且我不熟悉单个处理器(我已经使用了大约 10 种不同的处理器架构),它可以“循环这么多次”而无需某种“检查我们是否达到了数量”。
So, you will have to write some code that checks how many times you've repeated something (or, how many times there is left to do - there is an x86 instruction called "loop" that does just that - counts down, and if the counter is not zero, jump to beginning of the loop).
因此,您将不得不编写一些代码来检查您重复某事的次数(或者,还有多少次要做 - 有一个名为“循环”的 x86 指令可以做到这一点 - 倒计时,如果计数器不为零,跳到循环的开头)。
If the compiler wishes to then "unroll" a loop because it has a constant number of iterations, and it decides "unrolling this is faster" [compilers decide these sort of things all the time, and often get it right], then the compiler may well do so. But you still have to write code that "checks".
如果编译器然后希望“展开”一个循环,因为它具有恒定的迭代次数,并且它决定“展开这个更快”[编译器一直决定这些事情,并且经常做对],那么编译器可能会这样做。但是您仍然必须编写“检查”的代码。
回答by j b
If you want the syntactic nicety of being able to write repeat(x) {}
then you could use a macro.
如果您想要能够编写的句法细节,repeat(x) {}
那么您可以使用宏。
Something like:
就像是:
#include <iostream>
#define repeat(x) for(int i = x; i--;)
int main()
{
repeat(10)
{
std::cout << i << std::endl;
}
return 0;
}
The implementation here also uses a comparison to zero in the for loop rather than the less than operator, which may be slightly faster.
这里的实现还在 for 循环中使用了与零的比较,而不是小于运算符,后者可能会稍微快一些。
回答by DonMathi
How about this:
这个怎么样:
typedef std::vector<int> times;
for (auto count : times(5))
{
// execute the loop 5 times
}
回答by Nomad101
I would have to say that the biggest increase in speed would be the fact that you are not allocating an iteration variable, but what you asked for would inevitably need to check a condition. in essence what you have there is as follows.
我不得不说,最大的速度提升是您没有分配迭代变量,但是您所要求的将不可避免地需要检查条件。本质上,您拥有的内容如下。
int i = 0;
for(; i< 50; i++)
{
Do Something.
}
The reason I have moved I to outside the for loop is to state it can be any variable initialized before the loop. It is percisely the same thing as,
我将 I 移到 for 循环之外的原因是声明它可以是在循环之前初始化的任何变量。完全一样,
for(int i =0; i< 50; i++)
{
}