C++入门
C++动态开辟空间的方式
malloc
int *pa = (int )malloc(sizeof(int));
malloc方法开辟的空间的返回的类型为 void*类型,需要强转为目标类型,空间中的内容为随机值。
malloc方法开辟一块空间
calloc
int pb = (int)calloc(2, sizeof(int));
calloc方法开辟”N”块空间(N等于参数一),空间中的内容为0;
new
int *a = new int; //开辟空间
delete a; //释放a
new 开辟空间相当于malloc 实际上是对malloc的一层封装,delete是对free的一层封装。
开辟的空间需要及时释放
构造方法
Stu stu1;
会隐式调用无参的构造方法。(注意不要加括号)
如果有多个构造方法,且有参数的构造方法每个参数都有默认值,那么会出现二义性
如果只有一个有参的构造函数,且有参的构造还有均有默认值,那么会调用有参的构造函数。
如果只有有参的构造函数,且参数没有默认值,会出错
2 构造函数调用时机,当对象被创建出来时。
使用explicit关键字修饰构造方法,可以阻止它们被用来执行隐式类型转换,但他们仍可以被用来进行显示类型转换。
1 | class A |
内存四区
代码区
存放函数体的二进制代码,由操作系统进行管理
全局区
存放全局变量和静态变量以及常量
栈区
有编译器自动分配释放,存放函数的参数值,局部变量等。
堆区
由程序员分配和释放,若程序员不释放,程序结束时由操作系统回收。
内存四区的意义:不同区域存放的数据,具有不同的生命周期,给我们更大的灵活编程。
程序运行前
在程序编译后,生成了exe可执行程序,未执行该程序前分为两个区域:
代码区:
存放CPU执行的机器指令
代码区是共享的,共享的目的是对于频繁被执行的程序,只需要再内存中由一份代码即可。
代码区是只读的,使其只读的原因是防止程序意外地修改了它的指令。
全局区:
全局变量和静态变量存放在此。
全局区还包含了常量区,字符串常量和其他常量(const修饰的全局变量)也存放在此。
该区域的数据在程序结束后由操作系统释放
程序运行后
栈区:
由编译器自动分配和释放,存放函数的参数值,局部变量等。
注意事项:不要返回局部变量的地址,栈区开辟的数据由编译器自动释放。
1 | int* func() |
堆区:
由程序员分配释放,若程序员不释放,程序结束后时由操作系统回收。
在C++中主要利用new在堆区开辟内存
1 | int* func() |
文件操作
文件操作需要包含头文件
文件类型分为两种:
文本文件:文件以文本的ASCII码形式存储在计算机中
二进制文件: 文件以文本的二进制形式存储在计算机中,用户一般无法直接读懂
操作文件的三大类:
- ofstream 写操作
- ifstream 读操作
- fstream 读写操作
文本文件
写文件:
写文件操作步骤:
包含头文件
#include
创建流对象
ofstream ofs;
打开文件
ofs.open(“文件路径”, 打开方式);
写数据
ofs << “写入数据”;
关闭文件
ofs.close();
文件的打开方式:(多个打开方式使用 “|” 连接)
打开方式 | 解释 |
---|---|
ios::in | 为读文件而打开文件 |
ios::out | 为写文件而打开文件 |
ios::ate | 初始位置:文件尾 |
ios::app | 追加方式写文件 |
ios::trunc | 如果文件存在先删除,再创建 |
ios::binary | 二进制方式 |
读文件:
写文件操作步骤:
包含头文件
#include
创建流对象
ifstream ifs;
打开文件
ifs.open(“文件路径”, 打开方式);
读数据
四种方式读取。
关闭文件
ifs.close();
eg:
1 | int main() |
二进制文件
以二机制的方式对文件进行读写操作打开方式要制定为 ios::binary
写文件
二进制方式写文件主要利用流对象调用成员函数write
函数原型: ostream& write(const char* buffer, int len);
参数解释: 字符指针buffer指向内存中一段存储空间。len是读写的字节数
eg:
二进制写对象
1 |
|
二进制读取写入图片
1 | //读取图片文件并写入新文件中 |
读文件
二进制方式读文件主要利用流对象调用成员函数read
函数原型:istream& read(char *buffer,int len);
参数解释:字符指针buffer指向内存中一段存储空间。len是读写的字节数
示例:
1 |
|
- 文件输入流对象 可以通过read函数,以二进制方式读数据
STL标准模板库
C++一种编程思想叫做泛型编程,用的主要技术就是模板。
C++提供了两种模板机制:函数模板和类模板
函数模板
作用:
建立一个通用函数,其函数返回值类型和形参类型可以不具体指定,用一个虚拟的类型来代表
语法:
1 | template <typename T> |
解释:
template –声明创建模板
typename – 表示其后面的符号是一种数据类型,可以用class代替
T – 通用的数据类型,名称可以替换,通常为大写字母
实例:
1 |
|
类模板
类模板作用:
- 建立一个通用类,类中的成员 数据类型可以不具体制定,用一个虚拟的类型来代表。
语法:
1 | template<typename T> |
解释:
template — 声明创建模板
typename — 表面其后面的符号是一种数据类型,可以用class代替
T — 通用的数据类型,名称可以替换,通常为大写字母
示例:
1 |
|
总结:类模板和函数模板语法相似,在声明模板template后面加类,此类称为类模板
C++11 中 using关键字可以替代typedef 给类型取别名:
区别: using可以在泛型中使用, typedef在泛型中使用必须借助结构体
1 | template <typename Val> |
Type traits 类型萃取
iterator 迭代器是算法与容器之间的桥梁
如果算法需要知道操作的容器的数据类型,算法需要从迭代器中获取到五个参数
1 | typedef Category iterator_category; // 迭代器类型 |
算法不会直接从迭代器中获取这个五个参数信息,(比如vector没有使用迭代器二十直接使用的指针),而是使用type traits获取五个参数信息。
vector扩容:
size()和capacity()区别
size()返回vector中的实际数据的数目
capacity()返回vector的容量大小(可能大于等于size)。
默认容量是0,每次扩容是之前的1.5倍,每次扩容都会使用一块新的内存,拷贝之前的所有数据,然后添加新的数据。
const修饰类的成员函数
const修饰类成员函数,实际修饰该成员函数隐含的 this 指针,表明在该成员函数中不能对类的任何成员进行修改。
常见问题
1、面向对象的三大特性:封装、继承、多态
2、类的访问权限:private、protected、public
3、类的构造函数、析构函数、赋值函数、拷贝函数
4、移动构造函数与拷贝构造函数对比
5、深拷贝与浅拷贝的区别
6、空类有哪些函数?空类的大小?
7、内存分区:全局区、堆区、栈区、常量区、代码区
8、C++与C的区别
9、struct与class的区别
10、struct内存对齐
11、new/delete与malloc/free的区别
12、内存泄露的情况
13、sizeof与strlen对比
14、指针与引用的区别
15、野指针产生与避免
16、多态:动态多态、静态多态
17、虚函数实现动态多态的原理、虚函数与纯虚函数的区别
18、继承时,父类的析构函数是否为虚函数?构造函数能不能为虚函数?为什么?
19、静态多态:重写、重载、模板
20、static关键字:修饰局部变量、全局变量、类中成员变量、类中成员函数
21、const关键字:修饰变量、指针、类对象、类中成员函数
22、extern关键字:修饰全局变量
23、volatile关键字:避免编译器指令优化
24、四种类型转换:static_cast、dynamic_cast、const_cast、reinterpret_cast
25、右值引用
26、std::move函数
27、四种智能指针及底层实现:auto_ptr、unique_ptr、shared_ptr、weak_ptr
28、shared_ptr中的循环引用怎么解决?(weak_ptr)
29、vector与list比较
30、vector迭代器失效的情况
31、map与unordered_map对比
32、set与unordered_set对比
33、STL容器空间配置器