指针和引用的区别
指针是一个变量,存储地址,引用只是原变量的别名
指针可以多级,引用只能一级,指针可以为空,引用必须初始化
指针可以改变指向,引用不行,改变指针不影响实参,引用可以影响
需要返回局部变量内存时用指针
对栈空间敏感(递归)使用引用,可以减少内存消耗
堆和栈区别
栈由系统自动分配,速度快,不会有碎片。默认大小4M
堆由程序员手动申请释放,速度慢,有碎片,大小一般是1-4G
栈顶和栈底是预设好的,向栈底扩展,大小固定,ulimit-a查看,ulimit-s修改
堆向高地址扩展,是不连续的内存区域,可以手动调整大小
new/delete malloc/free
malloc/free是库函数,支持覆盖。new/delete是运算符,支持重载
malloc/free仅分配回收空间,不会调用构造析构函数,分配类对象有风险,返回void类型指针,需要强制转换
new/delete会调用构造与析构函数,返回具体类型指针
free不会立马返回资源给操作系统,先用ptmalloc使用双链表保存,申请内存时返回合适大小,避免频繁调用
对于复杂数据结构,前四个字节存储数组大小,delete[]时根据数组大小重复执行n次析构函数
如何判断大小端存储
构造/析构函数执行顺序
析构与其相反
string和char*区别
内存对齐
每个变量空间要是整数倍,结构体是最大的整数倍
数组和指针区别
指针存着数组偏移量,函数传递指针效率高,不需要传输整个数组
强制转换
static_cast:没有运行时类型检查来保证转换的安全性。
const_cast<>里边的内容必须是引用或者指针
reinterpret_cast:将指针或引用转换为一个足够长度的整形,将整型转换为指针或引用类型
dynamic_cast:运行时处理的,运行时要进行类型检查。不能用于内置的基本数据类型的强制转换 要求 <> 内所描述的目标类型必须为指针或引用。
this指针
在成员函数开始前构造,结束时消除,存放在栈或者寄存器
在析构函数中delete this会导致this被无限释放
智能指针
share 大小是裸指针的2倍,绑定释放函数在运行期,makeshared只复制一次效率高
unique一般是一倍,性能好,绑定释放函数在编译期
无法复制,使用unique引用或者move
weak用于解决环形引用,lock()返回shared指针或者空指针
迭代器
++it不会产生临时对象性能高于后置
锁
vector
push back时如果size=0扩容一个单位,否则扩充2倍或者1.5倍
2倍扩容次数少但是不能利用之前释放的空间,1+2+4<8
1.5倍扩容空间利用率高
为什么不常数扩容,插入时间复杂度高于倍数O(1)
为什么析构函数要用虚函数
构造函数为什么不能是虚函数
构造函数不能用虚函数,因为没初始化没有生成vptr,无法找到vtable
虚函数表在常量区,虚函数在代码区
auto decltype
auto varname = value; //auto的语法格式
decltype(exp) varname = value; //decltype的语法格式
auto 根据=右边的初始值 value 推导出变量的类型;
decltype 根据 exp 表达式推导出变量的类型,跟=右边的 value 没有关系。
另外,auto 要求变量必须初始化,而 decltype 不要求,初始化与否都不影响变量的类型。
final
修饰类可以禁用类被继承,修饰成员可以禁止重写,但是可以重载
constexpr
编译器会将constexpr函数视为内联函数!所以在编译时若能求出其值,则会把函数调用替换成结果值。
const 变量的初始化可以延迟到运行时,而 constexpr 变量必须在编译时进行初始化。