例如for (int i = 0, h = arr.Count; i < h; i++)和for (int i = 0; i < arr.Count; i++)等等的一些写法

2011-03-20 02:51:32

13 Answers

先说下C# 的吧

刚好前几天和同事说这个事情的时候验证过.

for (int i = 0, h = arr.Count; i < h; i++)

for (int i = 0; i < arr.Count; i++)
在非常巨大的请求量下会有区别.

测试是10w的List或者Array,然后循环10次,大概是一倍的差距.

Javascript的请使用务必使用第一种写法,因为第二种会导致每次都计算count的,性能非常低下.

2011-03-20 04:31:30

其实我想说,对于如何编写高效的for循环程序,其实没必要纠结于那些什么i++和++i,当然这个纠结也有价值,但是总的来说付出和收获不对等。

一般情况下建议使用!=替换<,使用++i替换i++;虽然这个问题,不同的编译器是否会进行优化,或者说优化到什么程度,这个不好说。另外,对于for等之类的循环来说,一般情况下这些情况所消耗的性能基本可以忽略,我们应该将重点放置在for循环内部
普遍的经验是将for等循环内的东西能提取到循环外的就提取出来,尽量保持循环最小化的原则进行程序编写。

2011-03-20 06:50:46
  1. 使用++i代替i++的形式, 这个原因很明显
  2. 终止条件使用i != arr.Count 代替 i < arr.Count的形式, 使用!=位运算,而<需要做减法,显然位运算更快点,个人理解
  3. 如果arr.Count循环时是不变的,可以使用一个变量存储起来,int nCount = arr.Count; 总结 for (int i = 0; i < arr.Count; i++) 替换成 for (int i = 0; i != nCount; ++i)会高效很多,
2011-03-20 08:16:45

补充一点:

i++ 与++i的实质:

  1. i++

可以这样理解:i++,在被使用时,做了两个动作,先产生一个副本,然后本来的i(非副本)等于i的副本加1,然后使用i的副本。这个性质对当i是某个迭代器或指针是很有作用。
比如:iterator pos;erase(pos);pos++;这样做会error,因为pos在erase(pos)是被移除了,它就变成了一个“野的迭代器”;正确的写法是:iterator pos;erase(pos++);因为在移除之前,pos生成了一个副本pos0,然后执行pos=pos0+1指向下一个元素了,然后在移除pos的副本pos0。
更正一下:erase(pos++)这样写是不对的,我的理解是:在两个序列点中pos变化了两次,第一次移除,第二次自加;所以错了。个人理解是:pos++,在产生副本后被使用时不能被修改(只能使用)。
2.++i

++i:直接加1,然后被使用,它只有一个动作

2011-03-20 09:35:13

关于i++和++i @likebeta 的解释很合理。
其实for循环效率的优化可以考虑的写法主要还是:

  1. for循环的嵌套,最长循环放在内部可以提高效率
  2. 循环的展开一定程度上可以提高效率,可以参考这个问题的解答 @关于循环展开对性能的影响?{1322} http://www.dewen.org/q/1322/
  3. 其他有待了解
2011-03-20 11:25:53

说说我自己的一些想法,首先是for (int i = 0, h = arr.Count; i < h; i++)

for (int i = 0; i < arr.Count; i++)这两种写法,应该是第一种比较好,因为arr.Cout第一个只需计算一次,而第二种方法在每次判断时都需要计算arr.Count。
至于其他的在写for循环时要注意的我常遇到的就是遍历集合,我一般写成 for(obj : 集合)这样就不用判断集合是否为null了,其他的技巧一时半会就想不出来了。

2011-03-20 12:18:16
您不能回答该问题或者回答已经关闭!

相关文章推荐

  • C#中using指令的几种用法

    using + 命名空间名字,这样可以在程序中直接用命令空间中的类型,而不必指定类型的详细命名空间,类似于Java的import,这个功能也是最常用的,几乎每个cs的程序都会用到

  • C#实例解析适配器设计模式

    将一个类的接口变成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够一起工作

  • 使用托管C++粘合C#和C++代码(二)

    本文实现一下C++代码调用C#代码的过程。我构造一个简单并且直观的例子:通过C++ UI 触发C# UI.

  • C#开发高性能Log Help类设计开发

    项目中要在操作数据库的异常处理中加入写Log日志,对于商业上有要求,写log时对其它操作尽可能影响小,不能因为加入log导致耗时太多

  • Async和Await使异步编程更简单

    C#5.0中async和await两个关键字,这两个关键字简化了异步编程,之所以简化了,还是因为编译器给我们做了更多的工作

  • C#开发中的反射机制

    反射的定义:审查元数据并收集关于它的类型信息的能力。元数据(编译以后的最基本数据单元)就是一大堆的表,当编译程序集或者模块时,编译器会创建一个类定义表,一个字段定义表,和一个方法定义表等

  • C#运行时相互关系

    C#运行时相互关系,包括运行时类型、对象、线程栈和托管堆之间的相互关系,静态方法、实例方法和虚方法的区别等等

  • C#协变和逆变

    “协变”是指能够使用与原始指定的派生类型相比,派生程度更大的类型,“逆变”则是指能够使用派生程度更小的类型

  • C#中的索引器的简单理解和用法

    C#中的类成员可以是任意类型,包括数组和集合。当一个类包含了数组和集合成员时,索引器将大大简化对数组或集合成员的存取操作

  • C#基础概念之延迟加载

    延迟加载(lazy load)是Hibernate3关联关系对象默认的加载方式,延迟加载机制是为了避免一些无谓的性能开销而提出来的,所谓延迟加载就是当在真正需要数据的时候,才真正执行数据加载操作

  • 使用托管C++粘合C#和C++代码(一)

    C#在xml读写,数据库操纵,界面构造等很多方面性能卓越;C++的效率高,是底层开发的必备武器

  • 深入C# 序列化(Serialize)、反序列化(Deserialize)

    C#中的序列化和反序列化,序列化是.NET运行时环境用来支持用户定义类型的流化的机制