函数指针类型(F)(类型)和类型(类型)(类型)(类型)之间的差异
Difference between Type(f)(Type) and Type(*f)(Type) for function pointers?
这两个函数原型之间有什么区别?
void apply1(double(f)(double));
void apply2(double(*f)(double));
如果目标是将提供的功能应用于数组,那么与另一个版本相比,版本比其他版本更快?
编辑:实现的示例:
#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;
}
首先,模板包装器实例化的速度几乎完全受优化器的摆布。
也就是说,我将您的样本减少到我能想到的最基本的代码,特别是为了检查功能参数的调用。您可以继续阅读,但是您会看到它们调用完全相同。一项声明与另一个声明没有好处。此外,我包括了您遗漏的那个,(参考 - decl)
#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
__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
__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
__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:
它们是相同的(我怀疑它们会)。没有区别,我可以看到。
注意:值得一提
apply1: __Z6apply1IiEvT_PFS0_S0_E
apply2: __Z6apply2IiEvT_PFS0_S0_E
apply3: __Z6apply3IiEvT_RFS0_S0_E
void apply1(double(f)(double));
void apply2(double(*f)(double));
这两个功能具有相同的签名,因此没有差异。他们都采用一个指针来函数参数。
ISO/IEC 14882:2011 8.3.5 [DCL.FCT]/5:
确定每个参数的类型后,将" t"或" tharm返回t"类型的任何参数调整为"指向t"或"指针"或"指针函数返回t"。
我会尝试使它更简单。
#include <stdio.h>
void my_int_func(int x)
{
printf( "%dn", x );
}
int main()
{
void (*foo)(int);
// the ampersand is actually optional
foo = &my_int_func;
return 0;
}
您可以看到上面的函数,该函数需要一个整数并返回一个空白。在MAIN内部,我正在用My_int_func.进行函数指针FOO。请仔细查看评论" ampersand是可选的"。实际上,它说明了所有。
因此,您的两个陈述都没有区别。
相关文章:
- C++LinkedList问题.数据类型之间存在冲突?没有匹配的构造函数
- C ++中无符号位长度类型之间的隐式转换,即uint8_t,uint16_t
- 非类类型表达式的静态类型与动态类型之间的差异
- 如何使用静态多态性在 int 和指针类型之间进行转换?
- 在 Rcpp 中的字符串类型之间转换时出错
- 在硬件SIMD矢量指针和相应类型之间进行"interpret_cast"是一种未定义的行为吗
- "+=" 操作在类型之间不起作用 std::复杂<double>和__complex__双精度
- 您可以在具有相同表示形式的类型之间reinterpret_cast吗?
- 是std::memcpy在不同的可复制类型之间的未定义行为
- 包括数据类型之间的斗争
- 在不同类型之间转换常量指针
- 不同指针类型之间的无效比较:'type*' 和 'type&(*)()'
- 为什么 int 对象和函数类型之间不明确?
- C++20 中的严格别名规则是否允许标准 c++ unicode 字符和下划线类型之间"reinterpret
- 如何在任何两种类型之间reinterpret_cast
- 根据编译时条件在类型之间选择类型的惯用方法
- memcpy是否可以保留不同类型之间的数据
- 显式允许在主类型和用户定义类型之间进行类型转换
- 使用std::filesystem::path在分隔符类型之间进行转换
- 在函数指针类型之间转换