默认参数
- C++允许函数设置默认参数,调用时根据情况省略实参:
- 默认函数只能按照右到左的顺序
- 如果函数同时有声明、实现,默认参数是能放在函数声明中
- 默认参数的值可以是常量、全局符号(全局变量,函数名)
int age = 33;
void test() {
cout << "test()" << endl;
}
void display(int a = 11, int b = 22, int c = age, void (*func)() = test) {
cout << "a is " << a << endl;
cout << "b is " << b << endl;
cout << "c is " << c << endl;
}
int main() {
display()
return 0;
}
-
函数重载、默认参数可能会产生冲突、二义性(建议优先选择使用默认参数)
-
底层分析:
1.没有默认参数情况查看汇编:
int sum(int v1, int v2) {
return v1 + v2;
}
int main() {
sum(1, 2);
sum(3, 4);
}


2.有默认参数:

两种猜测:
猜测1:
sum(1, 4)
猜测2:
int sum(int v1, int v2) {
v2 = 4 ; return v1+v2;
}
汇编:




- E8 : 函数调用
- 为什么后面机器码不一样
后面这个是根据地址算出来的值, 所以机器码有一点点不一样 (只是机器指令的位置不一样 ,也可以认为是返回值地址)不用纠结

extern “C”
- 被 extern “C” 修饰的代码会按照C语言的方式去编译


- 两种写法
extern “C” void func() {
cout << "func()" << endl;
}
extern “C” void func(int age) {
cout << "func(int age)" << age << endl;
}
extern “C” {
void func() {
cout << "func()" << endl;
}
void func(int age) {
cout << "func(int age)" << age << endl;
}
}
- 如果函数同时有声明和实现,要让函数声明被extern ”C“修饰,函数实现可以不修饰

最终编译时函数名不同,所以不报错,可以同时存在
-
用于C、C++混合开发:
1.编译方式不一样,没法直接找到调用:
2.声明上加上extern “C”: 告诉编译器 用C语言方式编译的对应的函数

3.第三方库:函数声明.h文件, 函数实现.c文件

4.把头文件包含进去就可以了,include相当于把文件内容拷贝进去

5.直接加.h里面,这样更方便

6.如果C语言也要调用呢? 报错: 因为C语言环境 不认识 extern “C”

7.希望C++环境自动加上extern c, C语言环境不加:
C++ 环境编译器默认有个宏定义 :可以用这个宏判断是否是C++环境

利用这个宏 条件编译:

8.重复包含头文件造成浪费

利用宏判断:如果没定义过ABC 定义ABC
#ifndef ABC
#define ABC
...
#endif ABC
万一其他文件也用到相同的宏定义会出问题:

故为保证每个头文件里面的宏都是唯一的,用文件名:__MATH, __OTHER
9.自动防止头文件被重复包含:

- 防止文件被重复包含
常使用#ifndef、#define、#endif 防止头文件被重复包含
pragma once 可以防止整个文件内容被重复包含
区别:
1.#ifndef、#define、#endif 受C,C++标准支持,不受编译器的限制
2.有些编译器不支持 pragma once,较老的编译器不支持,兼容性不够好
3.#ifndef、#define、#endif 可以针对一个文件中的部分代码,而pragma once只能针对整个文件
内联函数(inline function):
- 使用inline修饰函数的声明或者实现,可以使变为内联函数
- 特点
- 编译器会将函数调用直接展开为函数体代码
- 可以减少函数调用开销
- 会增大代码吗的体积
- 尽量不要内联超过10行代码的函数
- 有些函数即使声明了,也不定会被编译器内联,比如递归函数


调用函数代价:开启栈空间,回收栈空间
一旦变为内联函数: 到时候执行这个代码的时候不存在函数操作,不存在栈空间开辟,直接执行代码什么时候使用内联函数提高效率:1.代码体积小 2.频繁调用
-
窥探内联函数本质:
1.普通函数:进行汇编调试
2.内联函数:
还是有函数调用,debug模式是不会有内联优化的

3.变成release模式:
调试:直接调用
由于编译器优化 连 + 操作都没有了 直接出现了30 (1E)

4.为窥探内联:
release模式开启禁止优化:
内联函数扩展:


不加内联:

-
内联函数和宏:
推荐使用内联函数:写代码的时候有语法检测和提示, 函数特性(传参)

表达式
-
C++有些表达式是可以被赋值的
Const
- const是常量的意思,被其修饰的变量不可修改
如果修饰的是类,结构体(的指针),其成员也不可以更改
-
下面五个指针分别是什么含义:
p3:

p1,p2:

p4,p5:

const修饰的是其右边的内容
![]()
网友评论