赞
踩
当函数带默认值的时候注意下面几点:
1.函数形参给默认值只能从右向左给;
当形参有默认值的时候传递参数直接push 值压栈即可。
2.调用效率问题:可以看到使用实参带默认值或者直接传值比传变量少了一句mov指令。
3.在函数定义是给默认值可以,在函数声明给默认值也是可以生效的。
4.形参给默认值的时候,不管是声明还是定义处给,形参默认值只能出现一次。(函数可以声明无数次)
inline内联函数和普通函数的区别?
inline内联函数在编译过程时在函数的调用点直接把函数代码展开处理了,所以没有函数调用开销了,; inline函数不再生成相应的函数符号;
上面回答都是大家会的,比较简单的理解。我们需要深层次解说:
函数的调用过程称为函数的调用开销:如果函数的代码很多,指令非常多,那么函数调用的开销(也就是栈开辟,栈帧调整的指令)跟函数本身的指令比较起来很多,那么就无所谓。但如果简单的函数在函数调用过程的开销已经大于函数本身指令执行的开销,那么使用内联函数比较合适。
内联函数就是编译器在编译过程中,直接在函数的调用点上将函数代码展开出来,就没有函数调用开销了,符号表也不会生成函数的符号了。但不是每一个函数前面加上inline都会被编译器处理成内联函数(比如递归不会,代码量复杂且多,展开有名字冲突就不展开),inline只是对编译器的一个建议,最终是否内联看编译器的处理。(inline在dubug模式没用,只有在release模式起作用)如果一个函数比较简单,在很多地方调用,被大量调用,那么应该设置它为内联函数。内联函数如果内联成功了,在符号表中不会生成符号的。
但过度使用inline也可能增加目标码的大小,因为造成了代码膨胀;
# 什么是函数重载?
函数重载要点1:一组函数,其中函数名相同,参数列表的个数或者类型不同,那么这一组函数就称作函数重载;
函数重载要点2:一组函数要称得上重载得先是处在同一个作用域当中的;
- /*我们知道变量是分全局变量和局部变量的,在一个函数中优先使用局部同名变量,
- 忽略全局同名变量;如果想使用全局同名变量,要加上::作用域运算符。*/
- #include <iostream>
- bool compare(char * a, char* b);
- int main() {
- bool compare(int a, double b);
- //在main函数作用域中,编译器优先调用这里的局部compare函数而不是全局compare函数。
- compare(3.14, 2.34);
- //发现调用的是局部作用域的compare版本,double 转int ,警告
- compare("hello", "world");
- //调用的是局部作用域的compare版本,char[]转int失败,显示错误
- return 0;
- }
-
- bool compare(char* a, char* b)
- {
- return false;
- }
- /*这个很重要,在我们继承结构当中,我们在考虑基类跟派生类,
- 也有函数名相同参数列不同的成员方法的时候,他们到底是一个重载、
- 隐藏还是覆盖的关系
- 这个一定要区分清楚。那第二点说什么意思呢?一组函数,
- 一组函数要称得上重载一定是处在同一个作用域当中*/
#编译器在编译过程中会根据函数调用时候传入的实参选择一个合适的版本。
注:volatile是c/c++一个关键字,在写多线程程序时候必不可少。volatile关键字是防止在共享的空间发生读取的错误。只保证其可见性,不保证原子性;使用volatile指每次从内存中读取数据,而不是从编译器优化后的缓存中读取数据,简单来讲就是防止编译器优化。在单任务环境中,如果在两次读取变量之间不改变变量的值,编译器就会发生优化,会将RAM中的值赋值到寄存器中;由于访问寄存器的效率要高于RAM,所以在需要读取变量时,直接寄存器中获取变量的值,而不是从RAM中。在多任务环境中,虽然在两次读取变量之间不改变变量的值,在一些情况下变量的值还是会发生改变,比如在发生中断程序或者有其他的线程。这时候如果编译器优化,依旧从寄存器中获取变量的值,修改的值就得不到及时的相应(在RAM还未将新的值赋值给寄存器,就已经获取到寄存器的值)。
函数重载要点3:但我们给函数加上const或者volatile的时候,是怎么影响形参类型的呢? 成员函数后面加const也可以构成重载关系;
函数重载要点4:函数的返回值跟函数重载没有关系,不能通过函数返回值确定重载(因为函数命名修饰生成函数符号的时候跟返回值没有关系)
报错:void func(int a); 函数和 void func(const int a);函数是不构成重载的,他们在编译器的眼里都是形参都是int;
经常问什么是多态?分为静态多态(编译时期的多态-函数重载和模板)和动态多态(运行时期的多态-虚函数)
1.C++为什么支持函数重载,C语言不支持函数重载?
C++编译器会对函数名会进行命名更改,会在原有的函数名后加上变量个数和变量类型等,所以表面上名字相同的重载函数经过编译器命名更改后的名字是不同的;
而c语言编译器知识简单的在函数名前加了下滑线,所以最后的函数名是相同的;那么之后的连接过程就会发生错误。
在c/c++里面是不允许在函数里面定义函数的,但是可以在一个函数里面声明一个函数;
2.函数重载需要注意什么?上面函数重载要点
3.C++和C语言代码之间如何相互调用?
使用extern "C"{}不仅可以实现在C代码中调用C++代码,还可以在C++代码中调用C代码;
在C++代码中调用C文件代码:
- //现在是test.c文件
- int sum(int a, int b) { //sum .text
- return a + b;
- }
- //现在是main.cpp文件
- #include <iostream>
- /*在C++代码中要用到那个c代码的函数,那么首先要在C++代码这里声明
- (也可以包含那个c文件的头文件)
- */
- /* int sum(int a, int b);//C++编译器函数名更改为:sum_int_int "UND"
- 编译过程中所有源文件都是单独编译的;链接的时候连接器发现这里有未定义符号,就在对符号的引用,
- 他就在其他obj或者.o文件里面去找sum_int_int这个符号,肯定找不到,因为C文件里面那个sum函数是
- 按照C语言的函数更改操作生成最终函数名的,与C++不同,所以找不见sum函数符号定义,所以这里
- C++调用C代码无法直接调用。怎么办呢?可以把sum函数定义括在extern "C"{}里面,这是告诉编译器
- 这个函数是在C语言规则下生成的,所以生成这个函数符号的时候要按照C语言编译器的规则。
- 之后链接时,就可以在定义sum函数的C语言文件里面找见定义了,那么符号解析就成功了,
- 就可以对符号分配虚拟地址进行重定向了。
- */
- extern "C" {
- int sum(int a, int b);
- //【sum函数声明】告诉编译器sum函数按照C编译器的函数符号生成规则进行生成。
- }
-
- int main() {
- int ret = sum(10, 20);
-
- }
C代码中调用C++代码:
- //Cpp文件里面
- extern "C" {
- int sum(int a, int b) { //sum_int_int .text
- return a + b;
- }
-
- }
- #include <stdio.h>
- int sum(int, int);
- /*函数声明:sum函数定义是在C++文件里面写的,这里C文件只是声明。
- 无法直接使用,会提示无法找到_sum符号,因为这是C文件,是按照C编译器对sum函数进行编译的,
- 最终生成的sum符号名是_sum,而sum函数在C++中的命名更改后是sum_int_int,所以符号链接错误。
- 所以我们需要把C++文件源码放在extern "C"{}里面*/
- int main() {
- int ret = sum(10, 20);
- printf("ret = %d \n", ret);
- return 0;
- }
看看下面常见的代码片段:
- /*只要是C++编译器,都内置了__cplusplus这个宏,
- 所以下面写了之后无论是用C++编译器还是C编译器去编译生成,都是可以让C项目来直接调用的。
- */
- #ifdef __cplusplus
- extern "C"{
- #endif // __cplusplusj
- int sum(int a, int b) {
- return a + b;
- }
- #ifdef __cplusplus
- }
- #endif // __cplusplus
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。