函数重载的概念是指形参类型不同,个数不同,参数不同。
c语言为什么不支持重载?c++为什么支持呢
首先c++的编译过程和c语言是一样的,会生成一个汇编代码
test.cpp中预处理首先是头文件展开,宏替换,去掉注释,条件编译
test.i中编译先检查语法,生成汇编代码(指令级别的代码)
test.s表示生成汇编代码,将汇编代码生成机器码
test.o表示链接 合并链接,生成可以执行程序
test.out//xxx.exe
只有声明没有定义就可能找不到,c语言直接用函数名去,c++用的修饰名
首先编译器里面有一个叫符号表的东西去存储函数名,本质是同样的函数名转换成两句指令,如果类型不同修饰出来的名不同,
返回值不同也不能构成函数重载,先不谈编译能否通过,在符号表翻译成的代码就不一样,名字不一样自然不能构成函数重载了
引用
引用实际就是给一个已经定义的变量取别名,使用&去引用,并不开辟额外的空间,从 汇编层来看引用就是指针
#include<iostream>
using namespace std;
int main() {
int a = 1;
int& b = a;
cout << &a << endl;
cout << &b << endl;
}
在传参中的意义非常重要
交换
void swap(int& a, int& b) {
int tmp = a;
a = b;
b = a;
}
单链表中的引用
链表为空的情况下如果没有使用引用的话,需要取地址然后传二级指针取地址
#include<iostream>
using namespace std;
typedef struct ListNode {
int val;
struct ListNode* next;
}ListNode;
ListNode* initNode(int val) {
ListNode* phead = (ListNode*)malloc(sizeof(ListNode));
phead->next = NULL;
phead->val = val;
return phead;
}
void PushBack(ListNode** phead,int x) {
ListNode* newnode = initNode(x);
if (*phead == NULL) {
*phead = newnode;
}
else {
ListNode* tail=*phead;
while (tail->next!=NULL) {
tail = tail->next;
}
tail->next = newnode;
}
}
int main() {
ListNode* plist = NULL;
PushBack(&plist, 1);
PushBack(&plist, 2);
PushBack(&plist, 3);
ListNode* phead = plist;
while (phead!=NULL) {
cout << phead->val << endl;
phead = phead->next;
}
}
在使用了引用的情况下,相当于给原链表娶了给别名,不需要取地址了,看上去更加简单
#include<iostream>
using namespace std;
typedef struct ListNode {
int val;
struct ListNode* next;
}ListNode;
ListNode* initNode(int val) {
ListNode* phead = (ListNode*)malloc(sizeof(ListNode));
phead->next = NULL;
phead->val = val;
return phead;
}
void PushBack(ListNode*& phead,int x) {
ListNode* newnode = initNode(x);
if (phead == NULL) {
phead = newnode;
}
else {
ListNode* tail=phead;
while (tail->next!=NULL) {
tail = tail->next;
}
tail->next = newnode;
}
}
int main() {
ListNode* plist = NULL;
PushBack(plist, 1);
PushBack(plist, 2);
PushBack(plist, 3);
ListNode* phead = plist;
while (phead!=NULL) {
cout << phead->val << endl;
phead = phead->next;
}
}
在结构体定义的时候,我们也可以定义了一个*PListNode的指针直接引用到函数内
#include<iostream>
using namespace std;
typedef struct ListNode {
int val;
struct ListNode* next;
}ListNode,*PListNode;
ListNode* initNode(int val) {
ListNode* phead = (ListNode*)malloc(sizeof(ListNode));
phead->next = NULL;
phead->val = val;
return phead;
}
void PushBack(PListNode& phead,int x) {
ListNode* newnode = initNode(x);
if (phead == NULL) {
phead = newnode;
}
else {
ListNode* tail=phead;
while (tail->next!=NULL) {
tail = tail->next;
}
tail->next = newnode;
}
}
int main() {
ListNode* plist = NULL;
PushBack(plist, 1);
PushBack(plist, 2);
PushBack(plist, 3);
ListNode* phead = plist;
while (phead!=NULL) {
cout << phead->val << endl;
phead = phead->next;
}
传引用返回传的是n的别名,返回局部变量或者临时变量的地址,销毁后是返回的野指针,可能会置随机值,也可能值会不变
此时打印的是1,1,1
int& count() {
int a[1000];
int n = 0;
return n;
}
int test() {
int a[1000];
int n = 1;
return n;
}
int main() {
int& ret = count();
test();
cout << ret << endl;
cout << ret << endl;
cout << ret << endl;
}
什么时候传引用返回?
全局对象or静态对象or堆上动态,出了作用域还在,提高效率,
coust引用
权限不能放大,但可以缩小和平移
int main() {
const int x = 0;
int& b = x;//权限的放大
const int& c = x;//权限的平移
int y = 0;
const int& d = y;//权限的缩小
}
int main() {
double x = 1.1;
const int& b = x;//权限的放大
cout << b << endl;//结果为1
}
宏函数
宏的缺点是什么?一种叫宏常量,一种叫宏函数,宏的优点是替换强,
宏函数
缺点:1是容易出错,语法坑多
2不能调试
3没有类型安全的检查
优点:1没有类型的严格限制
2针对小函数频繁调用,不用再建立栈帧
#define ADD(X,Y) ((X)+(Y))//不能不加括号(a|b+b&a)优先级会有问题
int main() {
int x=ADD(1, 2);
cout << x << endl;
}
内联函数inline
1、在调用的地方直接展开,不用建立栈帧
2、但是内联函数不能大量嵌套递归 直接展开系统会判定会不会为内联函数,假设100行的代码递归100次总共10000行,而普通函数只需要200行,一般10行左右可以内联函数展开
3、内联函数不能声明定义分离(不能分布在两个文件中)
inline int ADD(int x, int y) {
return x + y;
}
int main() {
int x=ADD(1, 2);
cout << x << endl;
}
关键字
auto
int a = 0;
auto b = a;//自动转换为int
auto c = &a;//自动转换为指针
注:auto不能作为函数的参数和定义数组
typeid.name()
cout << endl;
cout <<typeid(a).name() << endl;
for新规则
基于范围自动迭代
int arry[] = { 1.2,4,5 };
for (auto e : arry) {
cout << e << " ";
}
cout << endl;
for (auto& e : arry) {//不加引用代表的就是e不代表数组里的值
e *= 2;
}
for (auto e : arry) {
cout << e << " ";
}
不能在函数中形参使用指针的情况下使用auto
int fun(int array[]) {
for (auto e : arry) {
cout << e << " ";
}
}
nullptr
c++语法设计缺陷
NULL实际是一个宏,在传统的C头文件(stddef.h)中,可以看到如下代码:
#ifndef NULL
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void *)0)
#endif
#endif
void fun(int n) {
cout << "f(int)" << endl;
}
void fun(int* n) {
cout << "f*(int)" << endl;
}
int main() {
fun(0);//f(int)
fun(NULL);//f(int)
fun(((int*) NULL));//f*(int)
fun(nullptr);//f*(int)
}