字符
字符型
char ch='a' |
字符串
C风格:
char str[]="hello" |
C++风格:
|
※分文件编写
- 创建后缀名为.h的头文件
- 创建后缀名为.cpp的源文件
- 头文件中写函数的声明
- 源文件中写函数的定义
//swap.h头文件 |
//swap.cpp文件 |
//main.cpp文件 |
指针
在32位操作系统下占用4个字节,64位下占用8个字节(和数据类型无关!)
空指针
指针变量指向内存中编号为0的空间
- 用途:初始化指针变量
- 注意:空指针指向的内存不可访问!
int * p = NULL; |
内存编号为0~255为系统占用内存,不允许用户访问
野指针
指针变量指向非法的内存空间
int * p = (int *)0×1100; |
const修饰指针
三种情况:
int a=10; |
- 修饰指针—常量指针
特点:指针指向可修改,但指针指向的值不可修改
const int *p=&a; |
*p=20;//× |
- 修饰常量—指针常量(常指针)
特点:指针指向不可修改,指向的值可修改
int * const p=&a; |
*p=20;//√ |
- 既修饰指针,又修饰常量
特点:指针指向和指向的值都不可修改
const int * const p=&a; |
*p=20;//× |
技巧:看const右侧紧跟着的是指针还是常量,是指针就是常量指针,是常量就是指针常量
结构体
用户自定义的数据类型,允许存储不同的数据类型
定义&使用
语法:struct 结构体名 { 结构体成员列表 };
通过结构体创建变量的三种方式:
- struct 结构体名 变量名
- struct 结构体名 变量名={成员1值,成员2值…}
- 定义结构体时顺便创建变量
定义结构体变量时关键字struct不可省略
创建结构体变量时关键字struct可省略
struct student { ... } |
结构体数组
将自定义的结构体放到数组中,方便维护
语法:struct 结构体名 数组名[元素个数]={ {},{},… {}}
struct student arr[3]={ |
给数组中的元素赋值
arr[2].name="赵六"; |
结构体指针
通过指针访问结构体中的成员
- 利用操作符->可以通过结构体指针访问结构体属性
struct student s={ }; |
内存分区模型
- C++中在程序运行前分为全局区和代码区
- 代码区的特点是共享和只读
- 全局区中存放全局变量、静态变量、常量
- 常量区中存放const修饰的全局常量和字符串常量
new
在堆区创建整形数据
new返回的是该数据类型的指针
引用
语法:数据类型 &别名 = 原名
注意事项:
- 引用必须初始化,且初始化后不可改变
引用做函数参数
作用:函数传参时可利用引用的技术让形参修饰实参
优点:简化指针修改实参
//三种交换值方法:值传递、地址传递、引用传递 |
通过引用参数产生的效果同地址传递是一样的。引用语法更清楚简单。
*引用做函数返回值
引用可作为函数的返回值存在
不要返回局部变量的引用
函数的调用可作为左值
int& test(){ |
如果函数的返回值是引用,这个函数调用可作为左值
函数
函数默认参数
C++中函数才形参列表中形参是可以有默认值的
语法:返回值类型 函数名(参数=默认值){}
注意事项
若某个位置已有默认参数,那么从该位置往后,从左到右都必须有默认值
函数声明和实现只能有一个默认参数
函数占位参数
C++中函数形参列表里可以有占位参数,用来做占位,调用函数时必须填补该位置
语法:返回值类型 函数名(数据类型){}
//函数占位参数,占位参数也可有默认参数 |
※函数重载
满足条件:
- 同一作用域下
- 函数名称相同
- 函数参数类型不同 或者个数不同 或者顺序不同
注意事项
- 函数的返回值不可以作为函数重载的条件
void fun(int a,int b){} |
- 引用作为重载条件
void fun(int &a){} |
- 函数重载避免默认参数
类和对象
权限 | 访问权限 |
---|---|
公共权限public | 类内可以访问 类外可以访问 |
保护权限protected | 类内可以访问 类外不可访问 子类可以访问父类中的保护内容 |
私有权限private | 类内可以访问 类外不可访问 子类不可访问父类中的保护内容 |
构造函数&析构函数
构造函数
语法:类名(){}
- 无返回值 也不写void
- 函数名称与类名相同
- 可以有参数,即可以发生重载
- 程序调用对象时自动调用构造,无需手动调用,且只会调用一次
析构函数
语法:~类名(){}
- 无返回值 也不写void
- 不可以有参数,因此不可发生重载
构造函数的分类及调用
分类
两种分类方式:
- 按参数分:有参构造 无参构造(默认构造)
- 按类型分:普通构造 拷贝构造
//拷贝构造函数 |
调用
三种调用方式:
- 括号法
- 显示法
- 隐式转换法
void test(){ |
Person(10);//匿名对象,特点:当前执行结束后,系统会立即回收掉匿名对象
注意:不要利用拷贝构造函数,初始化匿名对象,编译器会认为Person(p3) === Person p3//对象的声明
拷贝构造函数调用时机
- 使用一个已经创建完毕的对象来初始化一个对象
- 值传递的方式给函数参数传值
- 以值的方式返回局部对象
构造函数调用规则
默认情况下,C++编译器至少给一个类添加3个函数
- 默认构造函数(无参,函数体为空)
- 默认析构函数(无参,函数体为空)
- 默认拷贝析构函数,对属性进行值拷贝
调用规则:
- 若用户定义有参构造函数,C++不再提供默认无参构造,但会提供默认拷贝构造
- 若用户定义拷贝构造函数,C++不再提供其他构造函数
※深拷贝与浅拷贝
面试经典问题,常见的一个坑
浅拷贝:简单的赋值拷贝操作
深拷贝:在堆区重新申请空间,进行拷贝操作
浅拷贝带来的问题:堆区的内存重复释放(利用深拷贝解决
总结:若属性有在堆区开辟的,一定要自己提供拷贝构造函数,防止浅拷贝带来的问题
初始化列表
Person(int a,int b,int c):a(a),b(b),c(c){ ... } |
类对象作为类成员
当其他类对象作为本类成员(对象成员),先调用对象成员的构造,再调用本类的构造,析构的顺序与构造相反
静态成员
在成员变量和成员函数前加上关键字static
静态成员变量
- 所有对象共享同一份数据
- 在编译阶段分配内存
- 类内声明,类外初始化
class person{ |
静态成员变量不属于某个对象上,所有对象都共享同一份数据
因此静态成员变量有两种访问方式
- 通过对象进行访问
person p; |
- 通过类名进行访问
cout<<person::a<<endl; |
有访问权限,私有权限访问不到
静态成员函数
- 所有对象共享同一个函数
- 静态成员函数只能访问静态成员变量
同上有两种访问方式,且有访问权限
空对象占用内存空间为:1
C++编译器会给每个空对象分配一个字节空间,是为了区分空对象占内存的位置
this指针
本质:指针常量
指向被调用的成员函数所属的对象
是隐含每一个非静态成员函数内的一种指针
用途:
- 当形参和成员变量同名时,可用this指针来区分
- 在类的非静态成员函数中返回对象本身,可使用return *this
const修饰成员函数
常函数
- 成员函数后加const后我们称为这个函数为常函数
- 常函数内不可以修改成员属性
- 成员属性声明时加关键字mutable后,在常函数中依然可以修改
常对象
- 声明对象前加const称该对象为常对象
- 常对象只能调用常函数
排序算法
冒泡排序
- 比较相邻的元素,若前一个比后一个大,交换他们两个
- 对每对相邻元素做同样工作,执行完毕后找出第一个最大值
- 重复以上步骤,每次比较次数-1,直到无需比较
- 外层循环:排序总轮数=元素个数-1
- 内层循环:每轮对比数=元素个数-排序轮数-1
杂项
- 数组个数计算方法:
sizeof(arr)/sizeof(arr[0])-1 |
- 随机数生成
|
visual studio中Ctrl+D快速复制当前一行
值传递时,函数形参发生改变,并不会影响实参