目录
注意: 如果a2是不存在的对象,a2 = a1 调用的是拷贝构造函数,调用的不是赋值运算符重载函数.
26.重载是编译时确定的(静态编译),虚函数是运行是绑定的(动态编译)。
29.如果类的构造函数访问权限不为public,对象的实例化同样可以。
31.如果有虚函数并且子类已经重写了,在父类的构造函数中被调用,在构造期间内是不执行多态的。
35.stack 和 queue 都是由deque来适配的。
40.对任何一棵二叉树,如果其终端节点数为n0,度为2的结点数为n2,则n0=n2+1。
43.指针变量进行自家运算后,地址偏移值为1,则其数据类型为?
45.哈希表在理论情况下在常数时间内查找到指定内容,针对的是没有哈希冲突的数据。
46.现有一循环队列,其队头指针为front,队尾指针为rear;循环队列长度为N。其队内有效长度为(假设队头不存放数据) (rear - front + N) % N。
1.进制
二进制 0101010 or 0101b
八进制 0开头,其中数字在0到7之间 012
十进制 12121
十六进制 0x123 or 123h
2.打印
%d 十进制打印
%o 八进制打印
%x 十六进制打印
3. const 修饰指针
常量指针:const 在*的前面,指的是所修饰的指针指向空间的值不能改变,即不能通过解引用改变指向的内容,但是指针的指向可以发生改变。
指针常量:const 在*的后面,指针本身是一个常量,指针的指向不能发生改变,但是可以通过解引用去改变指针所指向空间的值。
4.数组名
数组名只有在 & 或者sizeof之后表示数组本身,其余的都表示数组首元素地址。
5.计算一个数二进制有多少个1
int Onecounts(int x)
{
int count = 0;
while (x)
{
count++;
x = x & (x - 1);
}
return count;
}
6.printf
printf("%%%%")
一般情况下,%后跟o(八进制)d(十进制)x(十六进制)f(浮点类型)
现在%后面跟%是错误的格式,编译器会忽略%
例如:printf("%Q%Q"),会打印QQ。
7.char*a[] 和 char(*a)[]的区别
char*a[] 是数组,里面存放的是char*类型的元素。
char(*a)[x]是指针,指向长度为x的字符数组。
8.类定义
类中可以包含类成员和成员函数的定义和声明。
也可以只包含类成员和成员函数的声明,可以放在其他.cpp文件中,函数名前必须加类域。
9.构造函数
一般情况下,构造函数的访问权限是public
特殊情况下:一个类只能创建一个对象,将构造函数的访问权限设为private。
10.初始化列表
哪些变量必须在初始化列表初始化:
1.const修饰的成员变量
2.引用类型的成员变量
3.类类型对象,没有默认构造函数
初始化列表才是真正的初始化,在构造函数体内是赋值。
11.B b +3
如果类中具有含有一个参数的构造函数,那么这个构造函数具有类型转换的作用。
3会被转换成B的对象。
12.友元函数
友元函数不是类中的函数,但是可以访问类的私有成员。
13.重载函数
指的是在同一作用域下,函数名相同,参数列表不同的函数。
参数列表不同的具体体现: 参数个数不同、参数类型不同、类型次序不同.
注意,函数重载跟返回类型无关.
函数重载跟函数内部实现没有任何关系.
14.引用和指针传参
引用传参传给函数的不是值,因为引用的底层实现 是通过指针来实现的
所以引用传参和指针传参一样都是传地址.
15.拷贝构造函数
概念:是一个特殊的构造函数,参数的类型是一个类类型&,一般前面要加上const来修饰.
调用时机:当用已存在的对象去构造一个新的对象时,编译器会调用拷贝构造函数.
调用场景:
1.用一个以初始化的对象去初始化同一个类的另一个新对象.
A a1(1);
A a2(a1);
注意: 如果a2是不存在的对象,a2 = a1 调用的是拷贝构造函数,调用的不是赋值运算符重载函数.
2.调用函数形参和实参结合时.
void func(A a)
{}
int main()
{
A a;
func(a);
}
3.函数返回值是类的对象,函数执行返回调用时.
A func()
{
A a;
return a;
}
16.new 和 delete
new A
1.new
①、调用operator new(size)去申请空间,operator的底层是malloc。
②、调用类A的构造函数去初始化这片空间。
2.delete
①、调用类A的析构函数去释放资源。
②、调用operator delete释放空间,底层是free。
17.静态成员函数
1、在调用时没有隐藏的this指针。
2、在外面调用时,要加类名::,并不是通过对象调用。
3、类的静态成员函数只能访问类的静态成员,而不能访问非静态的成员。
18.静态成员变量
1、可以在类内初始化(特例):
const static int a = 1;
在类内这样是可以的,只能是const修饰的static的变量.
19.在c++中不能重载的运算符
有5个: . .* ?: sizeof ::
20.const修饰的变量
在c++中,const修饰的变量,在系统调用读取这个变量时,会直接使用变量中的内容替换变量。
21.类中什么都不写
编译器会自动生成:
1.默认构造函数(无参)
2.默认的拷贝构造函数
3.默认的赋值重载函数
4.默认析构函数
5和6. 两个默认的取地址重载函数
7.移动构造
8.移动赋值
22.析构函数中会报错的点
1.
~A()
{
delete this;
}
上述代码能通过编译,但是运行时一定报错。
2.析构函数作用是来释放资源,但是不一定类的成员变量都是从堆上开辟的,所以delete this会报错。
3.在析构函数中 将 this = NULL ,编译失败
因为 this类型是:类类型* const this->this指针的指向不能被改变。
23.关于栈和堆的动静态分配
堆只能动态分配
栈可以动态分配也可以静态分配
使用alloca可以申请栈的空间内存,用完会在退出栈时自动归还给系统。
24.虚函数可不可以被static修饰
不可以,因为被static修饰之后,函数体就不会含有this指针,而虚函数需要this指针去调用对象的信息从而去调动虚表。
25.纯虚函数
A
{
virtual void fuc() =0;
};
具有纯虚函数的类叫做抽象类,抽象类不能实例化对象。
纯虚函数不一定为空函数,可以有实现的函数。
虚基类是什么:被菱形继承且继承方式是virtual继承的 的最初的父类叫做虚基类。(具体可以看我前面的博客“C++中的继承_JJJ MODEST的博客-CSDN博客_c++的继承”)。
26.重载是编译时确定的(静态编译),虚函数是运行是绑定的(动态编译)。
27.为什么要把父类的析构函数定义为虚函数?
new一个子类对象被父类的指针所指向。
A *pa = new B;
delete pa;
如果父类的析构函数不是虚函数,那么在delete pa时只会根据类型去调用该类型的析构函数(父类的析构函数被调用),而不会去调用子类的析构函数,从而造成资源的泄露。
但如果父类的析构函数是虚函数,在delete时,会先调用子类的析构函数,在调用父类的析构函数。
28. const成员只能调用const成员函数。
这与const权限有关。
29.如果类的构造函数访问权限不为public,对象的实例化同样可以。
比如:
class A
{
public:
static A* construct()
{
return new A;
}
private:
A()
{
cout << "A::A()" << endl;
}
};
int main()
{
A* pa = A::construct();
}
因为静态函数不需要对象去调用,new会在创建空间之后会自动调用类的构造函数,从而实现对象的实例化。
30.子类能访问父类的什么?
无论继承权限是什么,在子类的函数中,只能访问原基类中的public和protected成员。
如果使用子类对象去调用,只能调用基类的public成员。
31.如果有虚函数并且子类已经重写了,在父类的构造函数中被调用,在构造期间内是不执行多态的。
同样的在析构函数中,如果调用的父类析构函数是虚函数,并且析构函数中要调用子类已经重写的函数,这时多态也是不执行的,因为构造时,先构造父类再子类,析构时,就是先析构子类再父类,当调用到父类的析构函数时,子类的成员都已经被释放空间,什么都没有了,则调不了子类的虚函数。
32. 重载 重写(覆盖) 隐藏(遮蔽)
重载:
1.在同一个作用域中
2.跟返回值无关
3.函数名必须相同
4.参数类型、顺序或数目不同(包括const参数和非const参数)
重写:
1.不同的作用域(分别为于派生类和基类之中)
2.函数名称相同
3.参数列表必须相同
4.基类函数必须是虚函数
隐藏:是指派生类的成员函数遮蔽了与其同名的基类成员函数
1.派生类的函数与基类的函数同名,但是参数列表有所差异。此时,无论有没有virtual关键字,基类的成员函数在派生类都将被隐藏。(就算有virtual但是两个函数之间的参数列表有所差异构不成重写)。
2.派生类的函数与基类的函数同名,但是参数列表也相同,但是基类没有virtual关键字。此时,基类的成员函数在派生类将被隐藏。
部分摘自《高质量程序设计指南》
33.数组在函数接收时作为形参,会退化为指针。
34.vector的成员函数erase
erase删除当前元素之后会返回下一个元素的迭代器。
具体删除流程是
35.stack 和 queue 都是由deque来适配的。
36.stl中的sort底层不光有 插入排序也有快速排序。
37.stl中的一级容器
一级容器:数据类型不能是组合类型,是基本类型。
像key-value类型就是键值对结构,是组合类型。
38.stl的6大组件
空间适配器 容器 迭代器 算法 仿函数 算法
priority_queue底层数据结构 heap,默认是大堆。
39.迭代器失效
1.序列式容器
vector迭代器失效:
①在遍历时,erase一个值之后,要想继续遍历,必须用变量来接受erase之后返回的下一个值的迭代器。
②erase之后,指向后面值的迭代器全部失效。
③insert之后,指向后面值的迭代器全部失效。
④insert 或者 push_back之后,先前变量指向的begin 和end全部失效。
dequeue
①insert到除首尾位置之外的任何位置都会导致迭代器。
②如果在首尾之外的任何位置erase,那么指向被删除元素外其他元素的迭代器全部失效。
③在首尾erase元素,那么指向元素的迭代器会失效。
2.关联式容器
map, set,multimap,multiset
①erase元素只会导致被删除元素的迭代器失效,所以要采用erase(迭代器++)的方式删除迭代器。
否则会报错。
②insert不会导致迭代器失效
40.对任何一棵二叉树,如果其终端节点数为n0,度为2的结点数为n2,则n0=n2+1。
41.排序的稳定性
稳定:冒泡排序 插入排序 归并排序
不稳定:直接选择排序 希尔排序 快速排序 快速排序
42.解决散列法中出现冲突问题采用的方法
线性探测法、多重散列法、链地址法
43.指针变量进行自家运算后,地址偏移值为1,则其数据类型为?
char unsigned char 空类
44.具有n个节点的完全二叉树的深度为log2N+1。
45.哈希表在理论情况下在常数时间内查找到指定内容,针对的是没有哈希冲突的数据。
46.现有一循环队列,其队头指针为front,队尾指针为rear;循环队列长度为N。其队内有效长度为(假设队头不存放数据) (rear - front + N) % N。
47.
未完待续...