delphi 可以将函数做为参数吗?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了delphi 可以将函数做为参数吗?相关的知识,希望对你有一定的参考价值。

可以。
参考Classes单元中TStringList.CustomSort,它就要求一个用于比较两行大小的函数作为参数,注意参数中的函数得先声明一个类型。
参考技术A 必要性不是很大,在调用某要用函数作为参数的函数前,定义一个变量,将那个参数函数的值给这个变量,用这个变量作参数不就行了。干嘛要标新立异,玩新花样呢?总之要有必要。 参考技术B 调用时可以传入函数

定义时没见过,但你可以把函数写在一个类(简单点就是form)里,将该类作为参数传入,需要改函数时,通过类名调用该函数
参考技术C 可以啊,回调函数嘛

我可以创建一个将形式参数传递给 C++ 函数的联合吗?

【中文标题】我可以创建一个将形式参数传递给 C++ 函数的联合吗?【英文标题】:Can I create a union with formal parameter passed to a function in C++? 【发布时间】:2011-10-26 16:04:27 【问题描述】:

下面的函数计算32位浮点值的绝对值:

__forceinline static float Abs(float x)

    union 
        float x;
        int a;
     u;
    //u.x = x;
    u.a &= 0x7FFFFFFF;
    return u.x;

函数中声明的union u 包含变量x,它与函数中作为参数传递的x 不同。有没有办法创建一个带有函数参数的联合 - x?

上面未注释行的函数执行时间长于这个函数有什么原因吗?

__forceinline float fastAbs(float a)

    int b= *((int *)&a) & 0x7FFFFFFF;
    return *((float *)(&b));

我正在尝试找出在尽可能少的读/写内存中获取浮点值的最佳方法。

【问题讨论】:

std::abs 相对于您的版本需要多长时间? 顺便说一句...为什么不使用 std::fabs?因为这将使用适当的 CPU 指令集来计算绝对值(在英特尔架构上它是 FABS),这将比你上面所做的要快得多。 艾哈迈德·马苏德:你确定吗?我现在将对其进行测试。 ...嗯,不完全理解为什么,但它得出的简单 fabs 函数是最快的:fabs - 0.922311,fastAbs(从上面) - 0.935108,Abs(也从上面) - 0.937011,abs on double - 0.936235。我对此有点好奇…… 【参考方案1】:

对于第一个问题,我不确定为什么您不能通过作业满足您的需求。编译器会做任何可以做的优化。

在您的第二个示例代码中。您违反了严格的别名。所以不一样。

至于为什么慢:

这是因为当今的 CPU 往往具有单独的整数和浮点单元。通过这样的类型双关语,您强制将值从一个单位移动到另一个单位。这有开销。 (这通常是通过内存完成的,因此您有额外的加载和存储。)

在第二个 sn-p: a 原来在浮点单元中(x87 FPU 或 SSE 寄存器),需要移动到通用寄存器中以应用掩码0x7FFFFFFF。然后需要将其移回。

在第一个 sn-p 中: 编译器可能足够聪明,可以将a 直接加载到整数单元中。所以你在第一阶段绕过了 FPU。

(在您向我们展示程序集之前,我不能 100% 确定。它还很大程度上取决于参数是从寄存器开始还是从堆栈开始。以及输出是否立即被另一个浮点运算使用.)

【讨论】:

第一个版本也是 UB,您只能读取最后写入的联合成员(除非在 C++11 中更改)。 我知道在 C99 中,你可以通过联合来实现。但我不确定 C++11。【参考方案2】:

查看发布模式下编译的代码的反汇编,差异非常明显! 我去掉了内联,使用了两个虚函数,让编译器不要优化太多,让我们展示一下差异。

这是第一个函数。

013D1002  in          al,dx  
            union 
                float x;
                int a;
             u;
            u.x = x;
013D1003  fld         dword ptr [x]   // Loads a float on top of the FPU STACK.
013D1006  fstp        dword ptr [x]   // Pops a Float Number from the top of the FPU Stack into the destination address.
            u.a &= 0x7FFFFFFF;
013D1009  and         dword ptr [x],7FFFFFFFh  // Execute a 32 bit binary and operation with the specified address.
            return u.x;
013D1010  fld         dword ptr [x]  // Loads the result on top of the FPU stack.
        

这是第二个功能。

013D1020  push        ebp                       // Standard function entry... i'm using a virtual function here to show the difference.
013D1021  mov         ebp,esp
            int b= *((int *)&a) & 0x7FFFFFFF;
013D1023  mov         eax,dword ptr [a]         // Load into eax our parameter.
013D1026  and         eax,7FFFFFFFh             // Execute 32 bit binary and between our register and our constant.
013D102B  mov         dword ptr [a],eax         // Move the register value into our destination variable
            return *((float *)(&b));
013D102E  fld         dword ptr [a]             // Loads the result on top of the FPU stack.

第一种情况下浮点运算的次数和FPU栈的使用量更大。 这些功能完全按照您的要求执行,所以不足为奇。 所以我希望第二个函数更快。

现在...删除虚拟和内联的东西有点不同,很难在这里编写反汇编代码,因为编译器当然做得很好,但我再说一遍,如果值不是常量,编译器将使用第一个函数中的更多浮点运算。 当然,整数运算比浮点运算快。

你确定直接使用 math.h abs 函数比你的方法慢吗? 如果正确内联,abs 函数就会这样做!

00D71016  fabs  

这样的微优化很难在长代码中看到,但如果您的函数在长链浮点运算中被调用,fab 会更好地工作,因为值已经在 FPU 堆栈或 SSE 寄存器中!编译器会更快更好地优化 abs。

您无法衡量在一段代码中运行循环的优化性能,您必须了解编译器如何在实际代码中混合在一起。

【讨论】:

我现在测试了 fabs 功能,结果更快。似乎我愚蠢到相信手动设置最高有效位比晶圆厂更快的“事实”,但事实证明并非如此。我现在将删除我的“fastAbs”功能并用 fabs 替换它。谢谢你们的好解释! 我也在我的应用程序中对其进行了测试,确实代码运行得更快了!很高兴我问了这个问题,因为对一些不必要的东西进行分类并不好。

以上是关于delphi 可以将函数做为参数吗?的主要内容,如果未能解决你的问题,请参考以下文章

Delphi DLL 可以在 C# 中被 PInvoked 和使用吗?

delphi 9 exportgridtoexcel第一个参数是文件名吗

c# 请问数组能作为参数传递吗? 如果可以如何传递呢?

delphi函数里面不可以出现控件吗

delphi中覆盖override父类的静态方法和虚函数有啥不同?

指针能作为引用参数吗?