深拷贝与浅拷贝
浅拷贝:
- 默认拷贝构造函数
- 问题:当有指针时,析构两次,指针悬浮
深拷贝:在内存中另外申请空间来存储数据
构造和析构顺序
构造:先父后子
析构:相反
new/malloc
- 属性:new是关键字,需要编译器支持;malloc是库函数,需要头文件支持
- 参数:new不需要显式指明大小,malloc需要显式指明大小
- 返回类型:分配成功后new返回对象类型的指针,malloc返回void*,需要类型转换
- 失败:new失败了抛出异常,malloc失败了返回null
- 重载:new/delete可以重载
- 内存区域:new从自由存储区,malloc从堆
智能指针
- 是什么
C++11,构造一个类,构造时传入一个普通指针,稀狗时释放,可以自动正确销毁,防止泄露。
通用实现:引用计数法。新建时计数器设置为1,引用时加一,赋值时左边加一右边减一,调用析构减一。
基于引用计数的智能指针的实现,需要实现构造,析构,拷贝构造,=操作符重载,重载*-和>操作符。 - 为什么
- 防止忘记释放,内存泄漏
- new失败后无法释放,造成浪费
- 四种指针
- auto_ptr: 不能赋值和拷贝,不报错,不能管理数组(析构是delete不是delete[]), 不能用于STL
- unique_ptr: 不能赋值和拷贝,报错。可用作返回值,在某个函数中返回动态申请内存空间的权限,相当于移动拷贝
PS: 与shared_ptr不同,unique_ptr拥有它所指向的对象,在某一时刻,只能有一个unique_ptr指向特定的对象。当unique_ptr被销毁时,它所指向的对象也会被销毁。因此不允许多个unique_ptr指向同一个对象,所以不允许拷贝与赋值。 - shared_ptr: 引用计数,可赋值
- weak_ptr: 循环计数问题—》没有引用计数,不保证内存地址有效,使用前要检查是否为空指针
强引用,弱引用
map红黑树
为什么用红黑树实现?
有序键值对
红黑树特点
- 只有红和黑
- 根节点是黑
- 外部节点都是黑
- 如果一个节点是红,则其子节点一定是黑(保证从根到任意外部节点不会有两个连续的红)
红黑树用法
保证任意根到叶子最长路径不会比最短路径长两倍,没有AVL那么严格,在增删查较多时效率更高
- AVL: 所有节点为根的树子树高度差不超过1
多态
一个接口多种实现
静态多态:编译时。重载,泛型—》程序调用函数,编译器决定运行哪一个
动态多态:运行时。继承,虚函数。通过指向派生类的基类指针决定访问派生类中同名覆盖函数。
重载/覆盖/隐藏区别:
重载:参数列表或者返回值不一样
覆盖(重写):继承时派生类函数覆盖基类
隐藏:派生类函数屏蔽与之同名的基类函数
虚函数与纯虚函数:
- 纯虚函数没有实现
- 虚函数子类可以不重载,纯虚函数子类必须实现
- 有纯虚函数的类是虚基类,不能直接生成对象
左值右值
右值引用
左值引用要求右边的值必须能够取地址,如果无法取地址,可以用常引用;
但使用常引用后,我们只能通过引用来读取数据,无法去修改数据,因为其被const修饰成常量引用了。
那么C++11 引入了右值引用的概念,使用右值引用能够很好的解决这个问题。
右值:纯右值,将亡值
对象交接资源释放和分配的问题,提高效率
解决泛型函数的问题