**************************原创,转载请标明出处。**********************************
目录
一、C与C++区别
1. 函数区别
概念:在函数声明或者定义的时候,给参数一个默认值。调用该函数的时候,实参不传值,就会按照之前的默认值传参。(特点里的作用域指的是单文件,单文件是不包含.h的文件,就是单纯的cpp)
特点一:函数参数的默认值,是在编译阶段生成指令的时候,直接生成入参指令
特点二:函数参数的默认值只能传递常量
void fun1(int a, int b, int c = 20)
{
cout << a << endl;
cout << b << endl;
cout << c << endl;
}
int main()
{
fun1(12,23);
return 0;
}
特点三:函数参数的默认值,只能从左向右依次赋值,不能反着也不能跳过
特点四:函数的默认值参数在同一作用域只能赋值一次,不能重复赋值。
void fun1(int a, int b, int c = 10);
void fun1(int a, int b, int c = 20)
{
cout << a << endl;
cout << b << endl;
cout << c << endl;
}
int main()
{
fun1(12,23);
return 0;
} //报错:重定义默认参数
特点五:因为函数参数的默认值是在编译时期带入的,所以函数参数的默认值只在本文件有效(当申明和实现,默认值不一样,作用域则是本文件)
1.2 inline与内联函数
概念:realse版本里,调用内联函数时候,该函数会在调用点展开,展开的阶段是编译阶段。展开可以理解为这里没有开辟新的函数栈帧(没开辟空间),然后入参等调用该函数;而是直接用代码替换了这里的函数调用语句。(一种理解方式)
在debug版本,内联函数和正常函数调用方式一致。
特点一:由于内联函数在编译阶段展开,编译阶段无法获取变量的值,而递归函数的终止条件一定需要有变量参与,所以,递归函数不可能被处理成内联函数(什么函数不能被处理成内联函数?)
特点二:inline 只是对系统的建议,建议将该函数处理为内联。(具体根据编译器来确定,一般简短的代码可以处理成内联函数)
特点三:inline函数在debug版本生成的是local的符号。如果成功建议成内联,在release版本
将不生成符号,直接在调用点展开。
宏函数 | static函数 | 内联函数 | 普通函数 | |
---|---|---|---|---|
展开的阶段 | 预编译时期在调用点展开 | 不展开 | debug版本不展开,release版本在调用点展开 | 不展开 |
是否可以调试 | 无法调试 | 可以调试 | 可以调试 | 可以调试 |
安全校验 | 没有类型安全校验 | 有类型安全校验 | 有类型安全校验 | 有类型安全校验 |
开辟空间 | 没有栈帧的开辟 | 有栈帧开辟 | debug版本有栈帧开辟,release版本没有栈帧开辟 | 有栈帧开辟 |
作用域 | 单文件可见 | 单文件可见 | 单文件可见 | 多文件可见 |
符号 | 不生成符号 | 生成local的符号 | debug版本生产local符号,release版本不生成符号 | 生成global符号 |
1.3 函数重载
概念:函数名相同,参数列表不同(返回值类型无影响)
特点一:C语言生成函数符号依赖函数名,C++产生函数符号依赖函数名和参数列表(返回值不受影响)
特点二:函数重载在编译时期决定调用哪个函数——静多态的一种
2 .c 与 .cpp 相互调用
C++调用C: (下面都是没有引入头文件,在几个.cpp、.c之间使用)
方法: Extern关键字:使用c语言方式编译代码
.cpp文件:
extern "C"
{
void fun_C()//fun_C
{
printf("void fun_C()");
}
}
//这里面也可以包含 .c的头文件
//extern "C"
//{
// #include "add.h" // 由add.h和add.c组成
//}
main()
{
//c++ 代码,调用上面函数
}
C调用C++:
方法: 需要一个中间的函数,衔接C++代码 到 C的调用
fun.cpp:
int fun_CPP(int a)//fun_CPP_void
{
cout << "void fun_CPP()" << endl;
return 0;
}
temp.cpp:
int fun_CPP(int a);//fun_CPP_int
extern "C"
{
int fun_CPP_tmp(int a)//fun_CPP_tmp
{
return fun_CPP(a);//fun_CPP_int
}
}
main.c:
int fun_CPP_tmp(int a);//fun_CPP_tmp
int main()
{
int a = 10;
fun_CPP_tmp(a);//fun_CPP_tmp
return 0;
}
3. 补充,符号
概念:符号由数据和指令组成。 数据:全局的变量,静态的变量。除了前面两个,其他的都叫指令。(比如调用函数的语句,就叫指令)。
特点一:所有的数据都会生成符号,指令中只有函数名会生成符号。
特点二:符号:全局符号(global)- 所有文件可见
局部符号(local)- 只有本文件可见
特点三: Inline函数在debug版本生成的是local符号,如果处理为内联之后在Release版本不生成符号,直接在调用点展开。
4. 问答:
为什么函数默认参数只能是常量?
函数默认参数的入参在编译阶段,编译时期可以得到常量的值,无法得到变量的值。所以函数默认参数只能是变量。
什么函数不能成为内联函数?
内联是在编译期间展开,编译生成指令。内联在这儿生成展开的指令,函数指令。递归不能内联,编译时期拿不到变量的值,运行才能时期拿到递归的终止条件是变量。
为什么内联函数release不生成符号?
因为在调试点展开了。
为什么内联函数debug生成的local符号?
因为需要调试,看该函数的代码是否正确,所以生成符号。
又因为其本质是内联的,在编译期就要看到函数的定义(便于debug调试),所以它省去了und状态的函数声明符号寻找global函数定义符号这一步骤。所以它是local。即只在本文件有效。
函数的编译链接:
函数声明,在编译之后生成und状态的符号,und是未定义的意思。【编译阶段,生成可重定向文件】。
然后寻找全局global符号,即函数定义(函数实现)经过编译所生成的globa符号,进行链接。找到了,脱离und状态。没找到,报错,【链接阶段,生成可执行文件】
为什么static只在本文件有效?
因为他生成局部符号,局部符号(local)- 只有本文件可见。