• 【c/c++】cpp对c的函数增强


    目录

    (1)内联函数

    1.含义

    2.使用内联函数替代宏代码片段

    (2)默认参数

    (3)占位参数

    (4)函数重载

    1.含义

    2.函数重载和函数默认参数的二义性报错

    3.函数重载和函数指针结合


    (1)内联函数

    1.含义

    C++编译器可以将⼀个函数进⾏内联编译,只需要在函数定义时前⾯加上inline即可。被C++编译器内联编译的函数叫做内联函数。内联函数在最终⽣成的代码中是没有定义的。C++编译器直接将函数体插⼊在函数调⽤的地方。

    1. #include
    2. inline int myfunc(int a, int b)
    3. {
    4. printf("a = %d\n", a);
    5. printf("b = %d\n", b);
    6. return (a < b) ? a : b;
    7. }
    8. int main()
    9. {
    10. int a = 1;
    11. int b = 3;
    12. int c = myfunc(a , b);
    13. return 0;
    14. }
    15. /*
    16. int main()
    17. {
    18. int a = 1;
    19. int b = 3;
    20. printf("a = %d\n", a);
    21. printf("b = %d\n", b);
    22. int c = (a < b) ? a : b;
    23. return 0;
    24. }
    25. */

    内联函数说明:

    • 内联函数省去了普通函数调⽤时压栈,跳转和返回的开销,速度更快。当函数体的执⾏开销远⼤于压栈,跳转和返回所⽤的开销 时,那么内联将⽆意义。
    • C++编译器不⼀定准许函数的内联请求!内联函数是对编译器的⼀种请求,因此编译器可能 拒绝这种请求。
    • 现代C++编译器能够进⾏编译优化,因此⼀些函数即使没有inline声明,也可能被编译器内 联编译。

    C++中内联编译的限制:

    • 不能存在任何形式的循环语句
    • 不能存在过多的条件判断语句
    •  函数体不能过于庞⼤
    • 不能对函数进⾏取址操作
    • 函数内联声明必须在调⽤语句之前
    • inline只是⼀种请求,编译器不⼀定允许这种请求

    2.使用内联函数替代宏代码片段

    C++中的const常量可以替代宏常数定义,如:

    const int A = 3;   与  #define A 3

    C++中是否有解决⽅案替代宏代码⽚段呢?(替代宏代码⽚段就可以避免宏函数的副作⽤)

    C++中推荐使⽤内联函数替代宏代码⽚段

    内联函数声明时inline关键字必须和函数定义(函数体)结合在⼀起,否则编译器会直接忽略内联请求。

    1. #include
    2. #define MYFUNC(a, b) (a < b) ? a : b //宏代码片段
    3. inline int myfunc(int a, int b)
    4. {
    5. return a < b ? a : b;
    6. }
    7. int main()
    8. {
    9. int a = 1;
    10. int b = 3;
    11. int c = MYFUNC(a++, b);
    12. std::cout << a << "," << b << "," << c << std::endl; // 3,3,2
    13. /*
    14. 为什么当 int c = MYFUNC(a++, b); 时
    15. 是a = 3, c = 2
    16. MYFUNC(a++, b) → (a++ < b) ? a++ : b
    17. a++先取值再自增 取值是1,自增后 a = 2,
    18. 1小于b所以返回 a++ ,返回的这个a++先取值就是2,再自增就是3
    19. 所以 a = 3, c = 2
    20. */
    21. int x = 1;
    22. int y = 3;
    23. int z = myfunc(x++, y);
    24. std::cout << x << "," << y << "," << z << std::endl; // 2,3,1
    25. /*
    26. 为什么当 int z = myfunc(x++, y); 时
    27. 是 x = 2, z = 1
    28. x++传入实参 先返回值,也就是1,所以a为1
    29. 1和3比较返回1,所以z = 1
    30. */
    31. return 0;
    32. }

    (2)默认参数

    C++中可以在函数声明时为参数提供⼀个默认值, 当函数调⽤时没有指定这个参数的值,编译器会⾃动⽤默认值代替。

    普通参数放在函数参数位置的左边,默认参数放在右边,默认参数右边必须全是默认参数。

    1. #include
    2. void test(char pos, int a = 0, int b = 0)
    3. {
    4. std::cout << pos << "," << a << "," << b << std::endl;
    5. }
    6. int main()
    7. {
    8. test('S'); // S,0,0
    9. test('K', 10); // K,10,0
    10. test('N', 3, 2); // N,3,2
    11. return 0;
    12. }

    (3)占位参数

    函数占位参数:占位参数只有参数类型声明,⽽没有参数名声明。⼀般情况下,在函数体内部⽆法使⽤占位参数。

    1. #include
    2. int func(int a, int b, int)
    3. {
    4. return a + b;
    5. }
    6. int main()
    7. {
    8. int ret = func(1, 2, 5);
    9. std::cout << ret << std::endl; // 3
    10. return 0;
    11. }

    可以将占位参数与默认参数结合起来使⽤,作用:

    • 为以后程序的扩展留下线索
    • 兼容C语⾔程序中可能出现的不规范写法
    1. #include
    2. int func2(int a, int b, int=0)
    3. {
    4. std::cout << a << "," << b << std::endl;
    5. }
    6. int main()
    7. {
    8. func2(1, 2); // ok
    9. func2(1, 2, 100); // ok
    10. return 0;
    11. }

    (4)函数重载

    1.含义

    概念:⽤同⼀个函数名定义不同的函数。当函数名和不同的参数搭配时函数的含义不同。

    函数重载⾄少满⾜下⾯的⼀个条件:

    • 参数个数不同
    • 参数类型不同
    • 参数顺序不同

    返回值 不是 判断函数重载的标准 

    1. // main.cpp
    2. #include
    3. void myPrint(int a)
    4. {
    5. printf("a = %d \n", a);
    6. }
    7. void myPrint(char *p)
    8. {
    9. printf("%s \n", p);
    10. }
    11. void myPrint(int a, int b)
    12. {
    13. printf("a = %d ", a);
    14. printf("b = %d \n", b);
    15. }
    16. int main()
    17. {
    18. myPrint(1);
    19. char name[] = "111222233aaaa";
    20. myPrint(name);
    21. myPrint(1, 2);
    22. return 0;
    23. }

    2.函数重载和函数默认参数的二义性报错

    1. #include
    2. // 函数重载 和 函数默认参数 在一起
    3. void myfunc(int a, int b, int c = 0)
    4. {
    5. std::cout << a << "," << b << "," << c << std::endl;
    6. }
    7. void myfunc(int a, int b)
    8. {
    9. std::cout << a << "," << b << std::endl;
    10. }
    11. int main()
    12. {
    13. myfunc(1, 2); //函数调用时,会产生二义性
    14. // 报错:错误:调用重载的‘myfunc(int, int)’有歧义
    15. return 0;
    16. }

    3.函数重载和函数指针结合

    当使⽤重载函数名对函数指针进⾏赋值时

    根据重载规则挑选与函数指针参数列表⼀致的候选者

    严格匹配候选者的函数类型与函数指针的函数类型

    1. #include
    2. #include
    3. using namespace std;
    4. int func(int x)
    5. {
    6. return x;
    7. }
    8. int func(int a, int b)
    9. {
    10. return a + b;
    11. }
    12. int func(const char *s)
    13. {
    14. return strlen(s);
    15. }
    16. typedef int (*PFUNC)(int a); // 函数指针声明
    17. int main()
    18. {
    19. int c = 0;
    20. PFUNC p;
    21. p = func;
    22. c = p(1); // 根据类型进行匹配,选择int func(int x)
    23. std::cout << c << std::endl; // 1
    24. // std::cout << p(1, 6) << std::endl; // 会报错
    25. // 在第一次p=func以及c = p(1)后,根据重载规则
    26. // p的地址已经确定,是int func(int x)函数的地址,因此这里报错
    27. return 0;
    28. }

    end

  • 相关阅读:
    持续集成(CICD)- Jenkins插件安装失败解决办法
    中国五氯化磷市场调研与投资预测报告(2022版)
    【java_wxid项目】【第九章】【Apache Mybatis集成】
    Python中的多线程(史上最简单易懂版)
    clickhouse 查看后台mutation任务
    文举论金:黄金原油全面走势分析策略独家指导
    MATLAB实现的图像分割之边缘检测和连接
    「Daily OI Round 4」Snow(贪心+模拟)
    three.js 场景中如何彻底删除模型和性能优化
    晚上下班之后做副业做什么好呢?
  • 原文地址:https://blog.csdn.net/hutaotaotao/article/details/138095408