目录
1.static的作用:
- 延长局部变量生命周期(不会多次创建,直到程序结束其生命周期才结束)
- static修饰的函数只能在本源文件中使用
- 其他文件无法使用static修饰的全局变量
普通的全局变量使用关键字 extern 可以达到跨文件调用的目的。
2.指针和引用
为什么经常把指针和引用对比:两者都是间接引用某个数据。
区别:
- 引用是别名,指针是指向地址的变量
- 引用没有解引用
- 引用必须赋初始值,指针可以不用(但一般防止其成为野指针还是会赋值为nullptr的)
- 引用不能更改,指针可以重新指向别的(引用相当于常指针)
- 有二级指针int**p = q,但是没有二级引用int&& a = b;
&&右值引用:
int && a = 10;
右值往往是没有名称的,使用它只能借助引用。和常量左值引用不同的是,右值引用还可以对右值进行修改。例如:
int && a = 10;
a = 100;
cout << a << endl;
程序输出结果为 100。
3.类的默认函数
- 构造函数
- 拷贝构造函数
- 析构函数
- 重载赋值运算符
- 重载取地址运算符
- const
- 移动构造函数和重载移动赋值操作符函数
4.#endif #defind #ifndef
C/C++的宏定义,防止该头文件被重复引用
#ifndef x :if not defined测试x是否被宏定义过
#ifndef x
程序段1//若x没有被宏定义过,定义x,并编译程序段1
#else
程序段2//若x已经定义过了则编译程序段2的语句,忽视程序段1
#endif
预处理:
1.宏定义:
无参的宏定义:#define N 100
有参的宏定义:#define S(a,b) (a+b)
2.文件包含
#include<>//直接在系统目录中查找
#incldue" "//先在工程目录中查找,找不到再在系统中查找
3.条件编译
#if...#else...#endif
#ifdef...#define...#endif
a##b
a##b 实际上就是ab,为了和防止别人定义的变量冲突我们可以定义一个宏,使我们自己的变量都带一个my_前缀,宏定义如下:#define MY_DECLARE(type,name) type my_##name;
#include<stdio.h>
#define MY_DECLARE(type,name) type my_##name;
void main()
{
MY_DECLARE(int,a) // 实际上宏展开为:int my_a;
my_a=88;
printf("%d\n", my_a);
}
5.五大内存区
- 栈区(向下增长):编译器自动分配释放,类似数据结构中的栈
- 堆区(向上增长):程序员分配释放,程序结束也会释放,分配方式类似链表
- 全局变量区:全局变量和静态变量,初始化和未初始化的分开放
- 文字常量区:字符串常量,一般为只读数据段
- 程序代码区,函数中的二进制代码
全局,static全局,局部变量,static局部变量,extern变量(外部),外部函数(另一个文件里面的函数),static函数
例:
p本身4字节在栈区,开辟的100个字节在堆区
int main()
{
char* p = (char*)malloc(100);
}
堆区和栈区的区别:
1.申请方式:
栈自动分配
堆程序员申请,并指明大小
2.申请后系统响应
栈的剩余空间大于申请空间就可以,否则异常:栈溢出
堆遍历空闲链表结点,寻找第一个大于申请空间的空闲链表结点,分配空间,将该链表从空闲链表中删除,记录结点,最后delete用
3.申请大小的限制
栈小
堆大,有虚拟内存空间
4.申请效率
栈效率高,堆效率低
5.内存
栈区内存空间有限
堆区空间很大,几乎没有限制
堆栈溢出
没有回收垃圾资源,层次太深的递归调用导致。
注意:没有死循环(堆栈溢出)
int main()
{
int a = 10;
while (a < a + 10)
a++;
cout << "main" << endl;
}
最后会输出main,程序结束。
内存泄漏:没有释放空间
6.常见排序算法
排序算法 | 平均时间复杂度 | 空间复杂度 | 稳定性 |
冒泡排序 | O(n^2) | O(1) | 稳定 |
选择排序 | O(n^2) | O(1) | 不稳定 |
插入排序 | O(n^2) | O(1) | 稳定 |
归并排序 | O(nlogn) | O(n) | 稳定 |
快速排序 | O(nlogn) | O(nlogn) | 不稳定 |
堆排序 | O(nlogn) | O(1) | 不稳定 |
希尔排序 | O(nlogn) | O(nlogn) | 不稳定 |
计数排序 | O(n+k) | O(n+k) | 稳定 |
桶排序 | O(n+k) | O(n+k) | 稳定 |
基数排序 | O(n*k) | O(n+k) | 稳定 |
7.不能声明为虚函数的
虚函数要等对象出来后再构造,运行时产生。
constructor,构造,拷贝构造(设置虚表指针),内联(编译时对象的拷贝,无映射关系),静态成员函数(所有同类对象共有)。
一般把析构函数设为虚函数,实现多态,程序编译时所有的析构函数名字都变成了destruction,合理的释放子类动态申请的空间;
8.switch()
不能switch()做的参数类型:浮点型(有精度),但是强制转换后可以
case后面的只能是定值;case可以嵌套.
int main()
{
int a = 4, b = 6;
switch (a + b)
{
case 10:
cout << a + b << endl;
break;
case 5:
cout << "lalala" << endl;
break;
}
}
9.五种循环
5种循环:for、while、do……while、if……goto、递归
for( ;1; )相当于while(1),也可以for(;;)
for (;;)
{
for (;;)
{
for (;;)
{
if (1)goto a;
}
}
a:cout << "end" << endl;
}