i + = a应等于i = i + a。 在a == 1的情况下,这被认为效率低于++ i,因为它涉及更多的内存访问;或编译器是否与++ i完全相同?
答案 0 :(得分:12)
很容易回答:C#编译器将C#源代码转换为IL操作码。没有专用的IL操作码执行与++运算符等效的操作。如果您使用ildasm.exe工具查看生成的IL,这很容易看到。此示例C#片段:
int ix = 0;
ix++;
ix = ix + 1;
生成:
IL_0000: ldc.i4.0 // load 0
IL_0001: stloc.0 // ix = 0
IL_0002: ldloc.0 // load ix
IL_0003: ldc.i4.1 // load 1
IL_0004: add // ix + 1
IL_0005: stloc.0 // ix = ix + 1
IL_0006: ldloc.0 // load ix
IL_0007: ldc.i4.1 // load 1
IL_0008: add // ix + 1
IL_0009: stloc.0 // ix = ix + 1
它生成完全相同的代码。抖动无法做任何事情,只能生成同样快速的机器代码。
前/后增量运算符是C#中的语法糖,只要它使代码更清晰,就可以使用它。或者更相关:避免它使它更少清晰可辨。他们确实有诀窍让你创造出有太多副作用的表情。
答案 1 :(得分:4)
编译器应该以你编写的方式优化代码,所以我相信i = i + 1与++ i相同。
答案 2 :(得分:2)
我不认为会有任何不同,但你可以把它付诸行动,例如:
class Program
{
static void Main(string[] args)
{
//Add values
List<objClass> lst1 = new List<objClass>();
for (int i = 0; i < 9000000; i++)
{
lst1.Add(new objClass("1", ""));
}
//For loop ++i
DateTime startTime = DateTime.Now;
for (int i = 0; i < 9000000; ++i)
{
lst1[i]._s1 = lst1[i]._s2;
}
Console.WriteLine((DateTime.Now - startTime).ToString());
//For loop i+=1
startTime = DateTime.Now;
for (int i = 0; i < 9000000; i+=1)
{
lst1[i]._s1 = lst1[i]._s2;
}
Console.WriteLine((DateTime.Now - startTime).ToString());
}
public class objClass
{
public string _s1 { get; set; }
public string _s2 { get; set; }
public objClass(string _s1, string _s2)
{
this._s1 = _s1;
this._s2 = _s2;
}
}
}
答案 3 :(得分:1)
这取决于。理论上,给定一个足够天真的编译器,++x
可能比x += 1
更有效。
但是,我不知道这种天真的编译器。
此外,现代CPU是高度复杂的野兽,可以并行执行大量操作,而且通常,通过与更大,更复杂的并行运行它们,可以完全隐藏这些“简单”操作。
一个好的经验法则,在优化时,一般写作时,尽可能清楚地表达你的意图。
这使得其他程序员更容易阅读您的代码,但也使编译器更容易这样做。
如果要增加值,请使用增量运算符(++
),因为它准确描述了您要执行的操作。
如果您想添加变量或未知值,请使用+=
运算符,因为就是它的。
如果您清楚自己的意图,那么编译器会获得有关您的代码的更多信息,并可以相应地进行优化。
如果你写x += 1
,你真的试图让编译器绊倒。您正在说“使用通用添加运算符将{1}}添加一个”。然后编译器必须弄清楚“好吧,你说使用通用添加,但我可以看到这是必要的,所以我只是要增加”。你可以告诉它。相反,现在你必须依赖编译器聪明。
答案 4 :(得分:0)
除非定义了一个const int == 1编译器如何在编译时知道a == 1?
所以答案必须是否定的,编译器无法将其编译为++ i。