首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >函数指针的Type(f)(Type)和Type(*f)(Type)之间的区别?

函数指针的Type(f)(Type)和Type(*f)(Type)之间的区别?
EN

Stack Overflow用户
提问于 2012-11-05 14:20:29
回答 3查看 510关注 0票数 3

这两个函数原型之间的区别是什么?

代码语言:javascript
复制
void apply1(double(f)(double));
void apply2(double(*f)(double));

如果目标是将提供的函数应用于数组,是否有比其他版本更快的版本?

编辑:实现示例:

代码语言:javascript
复制
#include <iostream>
#include <vector>
#include <cmath>

// First version
template<typename Type> void apply1(std::vector<Type>& v, Type(f)(Type))
{
    for (unsigned int i = 0; i < v.size(); ++i) {
        v[i] = f(v[i]);
    }
}

// Second version
template<typename Type> void apply2(std::vector<Type>& v, Type(*f)(Type))
{
    for (unsigned int i = 0; i < v.size(); ++i) {
        v[i] = f(v[i]);
    }
}

// Main
int main()
{
   std::vector<double> v = {1., 2., 3., 4., 5.};
   apply1(v, std::sin);
   apply2(v, std::sin);
   return 0;
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-11-05 14:51:04

首先,模板包装器实例化的速度几乎完全取决于优化器。

也就是说,我已经将您的示例简化为我能想到的最基本的代码,特别是为了检查函数参数的调用。您可以继续阅读,但您将看到它们调用的是完全相同的。一种声明与另一种声明相比没有任何好处。此外,我还包括了您遗漏的内容(reference-decl)

代码语言:javascript
复制
#include <cstdio>

int hello(int x)
{
    return x;
}

template<typename Type> 
void apply1(Type x, Type (f)(Type))
{
    f(x);
}

template<typename Type> 
void apply2(Type x, Type (*f)(Type))
{
    f(x);
}

template<typename Type> 
void apply3(Type x, Type (&f)(Type))
{
    f(x);
}

int main(int argc, char *argv[])
{
    apply1(1,hello);
    apply2(2,hello);
    apply3(3,hello);
    return 0;
}

扣除生成的实际asm为:

apply1

代码语言:javascript
复制
__Z6apply1IiEvT_PFS0_S0_E:
Leh_func_begin2:
    pushq   %rbp
Ltmp2:
    movq    %rsp, %rbp
Ltmp3:
    subq    $16, %rsp
Ltmp4:
    movl    %edi, -4(%rbp)
    movq    %rsi, -16(%rbp)
    movq    -16(%rbp), %rax
    movl    -4(%rbp), %ecx
    movl    %ecx, %edi
    callq   *%rax
    addq    $16, %rsp
    popq    %rbp
    ret
Leh_func_end2:

apply2

代码语言:javascript
复制
__Z6apply2IiEvT_PFS0_S0_E:
Leh_func_begin3:
    pushq   %rbp
Ltmp5:
    movq    %rsp, %rbp
Ltmp6:
    subq    $16, %rsp
Ltmp7:
    movl    %edi, -4(%rbp)
    movq    %rsi, -16(%rbp)
    movq    -16(%rbp), %rax
    movl    -4(%rbp), %ecx
    movl    %ecx, %edi
    callq   *%rax
    addq    $16, %rsp
    popq    %rbp
    ret
Leh_func_end3:

apply3

代码语言:javascript
复制
__Z6apply3IiEvT_RFS0_S0_E:
Leh_func_begin4:
    pushq   %rbp
Ltmp8:
    movq    %rsp, %rbp
Ltmp9:
    subq    $16, %rsp
Ltmp10:
    movl    %edi, -4(%rbp)
    movq    %rsi, -16(%rbp)
    movq    -16(%rbp), %rax
    movl    -4(%rbp), %ecx
    movl    %ecx, %edi
    callq   *%rax
    addq    $16, %rsp
    popq    %rbp
    ret
Leh_func_end4:

它们是完全相同的(正如我猜测的那样)。我看不出有什么不同。

注意:值得一提的是,编译器通过名称损坏检查来查看这些声明的方式:

代码语言:javascript
复制
apply1: __Z6apply1IiEvT_PFS0_S0_E
apply2: __Z6apply2IiEvT_PFS0_S0_E
apply3: __Z6apply3IiEvT_RFS0_S0_E
票数 5
EN

Stack Overflow用户

发布于 2012-11-05 15:28:40

代码语言:javascript
复制
void apply1(double(f)(double));
void apply2(double(*f)(double));

这两个函数具有相同的签名,因此应该没有区别。它们都有一个指向函数参数的指针。

ISO/IEC 14882:20118.3.5 dcl.fct / 5:

在确定每个参数的类型后,将任何类型为“数组T”或“函数返回T”的参数分别调整为“指向T的指针”或“指向返回T的函数的指针”。

票数 5
EN

Stack Overflow用户

发布于 2012-11-05 15:02:52

我会尽量让它更简单,you.Lets说有一个小程序:

代码语言:javascript
复制
#include <stdio.h>
void my_int_func(int x)
{
    printf( "%d\n", x );
}

int main()
{
    void (*foo)(int);
    // the ampersand is actually optional
    foo = &my_int_func;

    return 0;
}

正如你在上面看到的,有一个函数,它接受一个整数并返回一个void。在main中,我正在用my_int_func.And初始化一个函数指针foo,请仔细查看注释“与符号是可选的”。实际上,它说all.there在初始化时使用“和”和不使用“和”没有区别。

所以在你的两个陈述中没有区别。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13226942

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档