这周通过了人生中第一次面试,虽然只是字节实习生的一面,但起码证明这段时间学的还是有效果的,继续加油!
一、智能指针百分百安全吗,会不会出现内存泄漏?
答:会的,当两个对象互相使用shared_ptr成员变量指向对方,会造成循环引用,引起计数失效,从而导致内存泄漏。因此设立了weak_ptr指针,作用是不会修改引用计数的值,其类似一个普通指针,但不指向引用计数的共享内存,但是其可以检测到所管理的对象是否已经被释放,从而避免野指针非法访问。
二、map和哈希表的联系是什么?
答:map不是哈希表,其底层是红黑树。但二者对外使用上是一样的。不同的是,map内元素是由顺序的,对于有顺序要求的,map比较方便;对于需要频繁查找的,哈希表比较方便。
三、各排序算法总结
·冒泡排序:每次交换相邻两个元素,需要遍历n-1遍,时间复杂度是n^2,稳定;
·选择排序:每一次遍历找到第i个最小的元素,放到第i个位置,时间复杂度是n^2,不稳定;
·插入排序:每次遍历一个元素,放到前面对应的位置,时间复杂度是n^2,稳定;
·希尔排序:将数组分为几部分,分别进行插入排序,时间复杂度是n^2,稳定;
·归并排序:类似动态规划,先对每个小数组进行排序,再将它们进行合并,时间复杂度是nlogn,稳定;
·快速排序:每次选定一个元素,比其小的放到前面,比他大的放到后面;时间复杂度是n'^2,,不稳定;
·堆排序:将数组元素构造成一个堆,不断进行取出元素与堆的调整;时间复杂度是ologn,稳定。
四、求二叉树的深度,除了递归,还有什么方法?
答:还有层次遍历,记录层数。
五、sizeof运算符
答:sizeof是用来返回所占空间的字节数的运算符,其值在编译的时候已经计算好了,参数可以是数组、指针、对象、函数。
常见sizeof大小:
·sizeof(char) = 1;
·sizeof(short) = 2;
·sizeof(int) = 4;
·sizeof(long) = 4;
·sizeof(floar) = 4;
·sizeof(long long) = 8;
·sizeof(double) = 8;
·sizeof(A*) = 4(指针固定长度为4)。
六、野指针
答:没有初始化/原指针被delete后没有设置为nullptr/指针操作超过了变量作用范围都会导致野指针的出现。野指针顾名思义即指向不确定,因此会造成内存泄漏等不可预知的危险。
七、32位系统和64位系统的差别?
·要求硬件配置不同:64位操作系统只能安装在64位电脑上;
·寻址能力不:64位处理器控制内存能力好,导致虚拟内存更大;
·运算速度不同:64位一次可以提取64个数据,运算性能是32位的2倍。
八、越界报错出现的地址是什么?
答:数组越界访问有可能会修改其他不改的修改的内存,此时就会报错;但如果访问到的内存刚好是空的,就不会报错,但越界仍然是错误行为。
九、变量声明和定义的区别在哪?
答:区别在于是否需要建立空间。定义是需要建立存储空间的,但如果extern int a,说明a在别的文件中已经定义过了,就不会再为其建立存储空间了。
十、全局变量初始化和不初始化的存放位置相同吗?
答:从内存分区来看是相同的,都在全局存储区,但全局存储区内部也分几个区域,初始化的放在RW区中,未初始化的放在相邻的ZI区中。
十一、定义类指针,但不给具体对象时可以调用哪些内容?
答:如果调用的函数不需要实际对象的地址,就可以直接调用,例如直接cout;但如果需要具体的对象的成员值,就会出错。如果调用的是虚函数也会出错,因为虚函数是在构造函数中初始化的,没有构造函数就没有vptr,就无法访问虚函数。
十二、函数重载的实现原理?
答:编译器在编译阶段会创建一个字符串,用来指明函数的定义、类型等。C语言中该字符串较简单,C++中比较复杂和具体,因此C++中分的更细,不同的参数个数和类型在C语言中创建的对应字符串相同,无法区别。但在C++中就可以详细标明,区分开,因此可以实现重载。
十三、为什么要分配动态内存空间?
答:正常分配对象,该对象离开作用域就销毁了;动态分配的话什么时候销毁是由程序员自己控制,更为灵活。
十四、什么时候分配动态空间?
·分配不限制作用域的对象,对象存储在其特定的内存中,而不是内存中存储对象的拷贝;
·定义的对象会消耗大量内存时,防止栈区溢出,就通过动态分配到堆区去。
十五、重载重写和隐藏的区别
答:隐藏就是因为作用域的原因,外部成员对内部同名成员表现为隐藏;重写就是虚函数的实例化,也叫覆盖。
十六、C++在执行main函数之前执行哪些东西?
答:设置栈指针存放局部变量、初始化静态和全局变量、给未初始化的全局变量赋值、全局对象初始化、传值给main函数。