考虑一个返回结构的方法,如下所示: Public Function DoWork() As MyStructure Return New MyStructure(1.5, 1.7, 1.1, 55.9)End Function 在这种情况下,.NET是否创建并初始化MyStructure值一次或两次? 编辑:我的预
Public Function DoWork() As MyStructure Return New MyStructure(1.5, 1.7, 1.1, 55.9) End Function
在这种情况下,.NET是否创建并初始化MyStructure值一次或两次?
编辑:我的预感是,对DoWork的调用必须涉及.NET从一开始就在堆栈上推送返回值.否则,Return会如何回复调用代码?所以这是我正在谈论的第一次初始化.
第二个初始化将在Return语句中,其中参数1.5,1.7,1.1,55.9初始化一个新的MyStructure值.在返回时,.NET将使用新的返回值覆盖Stack上的现有值.
问题是,我对.NET的工作原理知之甚少.我对Stacks如何工作的概念是基于在DOS下,在80年代早期尝试在Pascal中编码的模糊回忆.我不知道.NET / Windows如何做这些事情!
只需看看生成的机器代码,看看会发生什么.您首先需要更改选项以确保启用优化程序,工具>选项>调试>一般>取消勾选“抑制JIT优化”复选框.切换到发布版本.在DoWork调用上设置断点,当它命中时使用Debug> Windows>反汇编以查看生成的机器代码.关于你所看到的,我会面对一点.你的直觉是正确的,只返回简单的标量值是有效的,它们适合CPU寄存器.不是这种结构,调用方法必须在其堆栈帧上保留空间,以便被调用者可以在那里存储结构.它传递指向该保留空间的指针.换句话说,如果您将此方法声明为Public Sub DoWork(ByRef retval As MyStructure),则没有实际区别.
只有通过内联函数,才能优化此代码的其他方式. x86抖动不会这样做,它对返回结构的方法很挑剔.事实上,x64抖动实际上是内联方法,但随后它完成了一个绝对可怕的工作.它仍然保留返回值的空间,然后生成许多不必要的初始化和值移动代码.非常残忍.这个抖动被重写为VS2015(项目名称RyuJIT),我还没有安装它,看它是否做得更好.
绘制的基本结论:此代码未优化.传递ByVal时,结构运行良好.不要让这个痉挛你的风格,我们在这里谈论纳秒.