- C++中常使用
cin
、cout
进行控制台的输入、输出cin
用的右移运算符 >>cout
用的左移运算符 <<endl
换行
getchar()
等待键盘输入,如果敲回车,就会读取键盘输入
- 规则:
- 函数名相同
- 参数个数、参数顺序、参数类型不同
- 注意:
- 返回值类型与函数重载无关,会造成歧义,直接报错
- 调用函数时,实参的隐式类型转换可能会产生二义性
- 本质:
- 采用了
name mangling
或者叫name decoration
技术 - C语言并不会根据参数进行改编、修饰,所以C语言不支持函数重载
- C++编译器默认会对
符号名
(函数名)进行改编、修饰 - 重载时会生成多个不同的函数名,不同编译器(MSVC、g++)有不同的生成规则
- 采用了
-
C++允许函数设置默认参数,在调用时可以根据情况省略实参。
- 默认参数只能按照右到左的顺序
- 如果函数同时有声明、实现,默认参数只能放在函数声明中
- 默认参数的值可以是常量、全局符号(全局变量、函数名)
- C语言也可以将函数名作为参数传递,只是没有默认参数
-
函数重载、默认参数可能会产生冲突、二义性(建议优先使用默认参数)
-
被
extern "C"
修饰的代码会按照C语言
的方式去编译
-
如果函数同时有声明和实现,要让函数声明被extern "C"修饰,函数实现可以不修饰
-
由于
C
、C++
编译规则的不同,在C、C++混合开发时,可能会出现以下操作:- 在C++调用C语言API时候,需要使用
extern "C"修饰C语言函数声明
- 在C++调用C语言API时候,需要使用
-
编写C语言代码中直接使用
extern "C"
,这样可以直接被C++调用,但是如果C语言调用就会报错,所有用以下方式:- 通过宏
__cplusplus
来区分C、C++环境
#ifdef __cplusplus extern "C" { #ifdef __cplusplus int sum(int a, int b); #ifdef __cplusplus } #ifdef __cplusplus
- 通过宏
-
使用
#ifndef
、#define
、#endif
来防止头文件的内容被重复包含 -
#pragma once
可以防止整个文件的内容被重复包含 -
区别:
#ifndef
、#define
、#endif
受C/C++标准库的支持,不受编译器的任何限制- 有些编译器不支持
#pragma once
,兼容性不够好 #ifndef
、#define
、#endif
可以只针对一个文件中的部分代码,而#pragma once
只能针对整个文件
- 使用
inline
修饰函数的声明或实现,可以使其变成内联函数- 建议声明 和 实现都增加
inline
修饰
- 建议声明 和 实现都增加
- 特点:
- 编译器会将
函数调用
直接展开为函数体代码
- 可以减少函数调用的开销
- 增大代码体积
- 编译器会将
- 注意:
- 尽量不要内联超过10行代码的函数
- 有些函数即使声明为
inline
,也不一定被编译器内联,比如递归函数
optimization level
- 内联函数和宏,都可以减少函数调用的开销
- 对比宏,内联函数多了语法检测和函数特性
- C++ 有些表达式是可以被赋值的
int a = 10;
int b = 20;
// a = 30
(a = b) = 30;
// 30 > 20 所以 b = 100
(a < b ? a : b) = 4;
const
是常量的意思,被其修饰的变量不可修改- 如果修饰的是
类
、结构体的指针
,其成员也不可以更改
- 如果修饰的是
const
修饰的是其右边
的内容
- C语言中,使用
指针(Pointer)
可以间接获取、修改某个变量的值 - C++中,使用
引用(Reference)
可以起到跟指针类似的功能。
int age = 20;
// refAge 就是一个引用
int &refAge = age;
- 注意点:
- 引用相当于是变量的别名(基本数据类型、枚举、结构体、类、指针、数组等,都可以有引用)
- 对引用做计算,就是对引用所指向的变量做计算。
- 在定义的时候就必须初始化,一旦指向了某个变量,就不可以再改变,“从一而终”。
- 可以利用引用初始化另一个引用,相当于多个别名
- 不存在引用的引用、指向引用的指针、引用数组
- 引用存在价值:比指针更安全、函数返回值可以被赋值
引用的本质
- 引用的本质就是指针(通过汇编分析,指针和引用的汇编代码一样),只是编译器削弱了它的功能,所以引用就是弱化了的指针
- 一个引用要占用一个指针的大小。通过结构体里面设置指针和引用分析得出。
int main() {
int age = 10;
// 指针
int *p = &age;
*p = 20;
return 0;
}
int main() {
int age = 10;
// 引用
int &refAge = age;
refAge = 30;
return 0;
}
- 指针和引用生成的汇编代码如下:
// 指针
`main:
pushq %rbp
movq %rsp, %rbp
xorl %eax, %eax
movl $0x0, -0x4(%rbp)
movl $0xa, -0x8(%rbp)
leaq -0x8(%rbp), %rcx
movq %rcx, -0x10(%rbp)
movq -0x10(%rbp), %rcx
movl $0x14, (%rcx) // 16 + 4 = 20
popq %rbp
retq
// 引用
`main:
pushq %rbp
movq %rsp, %rbp
xorl %eax, %eax
movl $0x0, -0x4(%rbp)
movl $0xa, -0x8(%rbp)
leaq -0x8(%rbp), %rcx
movq %rcx, -0x10(%rbp)
movq -0x10(%rbp), %rcx
movl $0x1e, (%rcx) // 16 + 14 = 30
popq %rbp
retq