我只想知道objective-c中的所有条件语句有什么区别,哪个更快更轻。
10 回答
一条建议:不要再担心哪些语言结构在微观上比其他语言结构更快或更慢,而应该关注哪些语言结构可以让你最好地表达自己。
与语言无关的版本(大多数情况下,显然这不包括声明性语言或其他奇怪的语言):
当我学习编程时(很久以前,我会坦率地承认),一种语言由三种执行指令的方式组成:
- 顺序(按顺序做事)。
- 选择(做许多事情之一)。
- 迭代(做某事零次或多次)。
if
和case
语句都是选择的变体。If
用于根据条件选择两个不同选项之一(使用伪代码):
if condition:
do option 1
else:
do option 2
请记住,else
在这种情况下可能不需要它是有效的else do nothing
。另请记住,选项 1 或 2 也可能包含任何语句类型,包括更多if
语句(称为嵌套)。
Case
略有不同 - 它通常意味着两个以上的选择,例如当您想要根据角色做不同的事情时:
select ch:
case 'a','e','i','o','u':
print "is a vowel"
case 'y':
print "never quite sure"
default:
print "is a consonant"
请注意,您可以使用case
两个选项(甚至一个),但这有点像用热核弹头杀死苍蝇。
While
不是选择变体,而是迭代变体。它属于for
,repeat
和until
许多其他可能性。
至于哪个最快,在绝大多数情况下都无关紧要。编译器编写者比我们普通人知道如何从他们的代码中获得最后一点性能。你要么相信他们能正确地完成他们的工作,要么你自己在汇编中手工编码(我更喜欢前者)。
通过专注于宏观视图而不是次要事物,您将获得更高的性能。这包括选择适当的算法、分析和定位热点。找到每个月需要五分钟的东西并在两分钟内运行它并没有什么好处。最好在每分钟发生的事情上获得较小的改进。
if
像,while
等语言结构case
已经尽可能快了,因为它们被大量使用并且相对简单。您应该首先编写代码以提高可读性,并且只在它成为问题时才担心性能(请参阅 YAGNI)。
即使您发现使用if/goto
组合而不是case
让您运行得更快一点,由此产生的源代码泥潭也更难维持下去。
while 不是条件它是一个循环。不同之处在于while循环的主体可以执行多次,而条件的主体只会执行一次或根本不执行。
if 和 switch 之间的区别在于 if 接受任意表达式作为条件,而 switch 只接受值进行比较。基本上,如果您有类似 的构造if(x==0) {} else if(x==1) {} else if(x==2) ...
,则可以使用 switch 更简洁(有效)地编写它。
案例陈述可以写成
if (a)
{
// Do something
}
else if (b)
{
// Do something else
}
但是这种情况要高效得多,因为它只评估条件一次然后分支。
while
仅当您希望多次评估条件并执行关联的代码块时才有用。如果您希望一个条件只出现一次,那么它相当于if
. 更贴切的比较是while
更概括的for
.
每个条件语句都有不同的用途,您不会在每种情况下都使用相同的。了解哪些适合哪种情况,然后编写代码。如果您分析您的代码并发现存在瓶颈,那么您继续解决它。在真正出现问题之前不要担心优化。
您是否在问 if 结构是否会比大循环中的 switch 语句执行得更快?如果是这样,我进行了快速测试,这段代码被放入了我刚刚在最新的 Xcode 和 iPhone SDK 中创建的基于视图的新项目的 viewDidLoad 方法中:
NSLog(@"Begin loop");
NSDate *loopBegin = [NSDate date];
int ctr0, ctr1, ctr2, ctr3, moddedNumber;
ctr0 = 0;
ctr1 = 0;
ctr2 = 0;
ctr3 = 0;
for (int i = 0; i < 10000000; i++) {
moddedNumber = i % 4;
// 3.34, 1.23s in simulator
if (moddedNumber == 0)
{
ctr0++;
}
else if (moddedNumber == 1)
{
ctr1++;
}
else if (moddedNumber == 2)
{
ctr2++;
}
else if (moddedNumber == 3)
{
ctr3++;
}
// 4.11, 1.34s on iPod Touch
/*switch (moddedNumber)
{
case 0:
ctr0++;
break;
case 1:
ctr1++;
break;
case 2:
ctr2++;
break;
case 3:
ctr3++;
break;
}*/
}
NSTimeInterval elapsed = [[NSDate date] timeIntervalSinceDate:loopBegin];
NSLog(@"End loop: %f seconds", elapsed );
此代码示例绝不是完整的,因为如前所述,如果您遇到的情况比其他情况出现的次数多,那么您当然希望将其放在前面以减少比较的总数。它确实表明,在决策或多或少在分支之间平均分配的情况下,if 结构会执行得更快一些。
另外,请记住,这个小测试的结果在设备上运行与在模拟器中运行之间的性能差异很大。代码注释中引用的时间是在实际设备上运行的。(显示的第一个时间是第一次运行代码时运行循环的时间,第二个数字是再次运行相同代码而不重建的时间。)
有条件语句和条件循环。(如果要信任维基百科,那么在编程中简单地引用“条件”并不包括条件循环。但这是一个次要的术语问题。)
Shmoopty 说:“由于这些陈述做不同的事情,争论哪个更快是荒谬的。”
嗯……这可能是浪费时间,但这不是荒谬的。例如,假设您有一个if
声明:
if (cond) {
code
}
您可以将其转换为最多执行一次的循环:
while (cond) {
code
break;
}
后者在几乎任何语言中都会变慢(或相同的速度,因为优化器if
在幕后把它变回原来的!)不过,在计算机编程中,有时(由于奇怪的情况)复杂的东西运行得更快
但这些事件很少而且相去甚远。重点应该放在你的代码上——什么使它最清晰,什么能抓住你的意图。
循环和分支很难简单解释,要从任何 c 风格语言的构造中获得最佳代码取决于所使用的处理器和代码的本地上下文。主要目标是减少执行管道的中断——主要是通过减少分支错误预测。
我建议你去这里满足你所有的优化需求。这些手册是为 c 风格的程序员编写的,如果您了解一些汇编,则相对容易理解。这些手册应该向您解释现代处理器的微妙之处、顶级编译器使用的策略以及构建代码以充分利用它的最佳方法。
我只记得关于条件和分支代码的最重要的事情。按如下方式订购您的代码
if(x==1); //80% of the time
else if(x==2); // 10% of the time
else if(x==3); //6% of the time
else break;
您必须使用 else 序列...在这种情况下,您的 CPU 中的预测逻辑将正确预测x==1
并避免 80% 的执行中断您的管道。
来自英特尔的更多信息。特别:
为了有效地编写代码以利用这些规则,在编写 if-else 或 switch 语句时,首先检查最常见的情况,然后逐步降低到最不常见的情况。对于静态分支预测,循环不一定需要任何特殊的代码排序,因为通常只使用循环迭代器的条件。
通过遵循此规则,您可以向 CPU 提供有关如何将其预测逻辑偏向于链式条件的提示。