记录一下面试以来遇到的编程语言相关问题及解答

C++相关问题及解答

简述智能指针及其实现原理

涉及公司:阿里云实习生

由于 C++ 语言没有自动内存回收机制,程序员每次 new 出来的内存都要手动 delete,有时候没有delete就可能会造成内存泄露的情况,此C++ 引用了智能指针。

智能指针是一个类,这个类的构造函数中传入一个普通指针,析构函数中释放传入的指针。智能指针的类都是栈上的对象,所以当函数(或程序)结束时会自动被释放。

一般实现智能指针可以采用辅助类的方式,需要实现构造,析构,拷贝构造,以及对一些解引用运算符。

简述C++多态及其实现原理

涉及公司:阿里云实习生、腾讯实习生

多态及其实现条件

c++中的多态就是在父类的函数前加上virtual关键字,在子类中重写该函数,运行时将会根据对象的实际类型来调用相应的函数,如果对象类型是子类,就调用子类的函数,如果对象类型是父类,就调用父类的函数。

多态的实现需要两个条件:

  • 虚函数重写,设置不同的状态
  • 对象调用虚函数时必须是指针或者引用

虚函数与重写

  • 虚函数是带有virtual关键字的成员函数
  • 子类有个和父类完全相同(函数名,形参,返回值都相同,协变和析构函数除外)的虚函数,就称子类虚函数重写父类虚函数

多态的原理

  • 多态是用虚函数表来实现的
  • 有虚函数的类都会生成一个虚函数表,在编译的时候使用
  • 虚函数表是一个存储虚函数地址的数组
  • 生成子类的虚函数表需要经过一下步骤
    • 将父类的虚函数表拷贝
    • 将子类中重写的虚函数覆盖掉父类中的虚函数
    • 如果有新增加的虚函数则放到表的最后
  • 在调用时会根据对象中的虚表指针来找实际应该调用的函数

其他问题

  • 虚函数和普通函数一样在代码段,虚表在只读常量区
  • inline函数(内联函数)没有地址,无法放到虚函数表中
  • 静态成员不能是虚函数,因为静态成员函数没有this指针,因为有this指针才能访问到虚表指针,有虚表指针才能找到虚表从而调用实际应该调用的函数
  • 构造函数不能是虚函数,因为对象中的虚函数表指针是在构造函数初始化列表阶段才初始化的
  • 析构函数可以是虚函数,并且最好把基类的析构函数定义成虚函数,当父类指针指向子类对象时,如果析构函数不是虚函数,析构就只会释放父类对象,造成内存泄漏
  • 普通对象访问普通函数和访问虚函数是一样快的(不会触发多态);指针对象或者是引用对象,调用普通函数更快一些,因为构成了多态,运行时调用虚函数要先到虚函数表中去查找。这样然后才拿到韩式的地址,这样就不如直接可以拿到函数地址的普通函数快。

C++中的extern C

涉及公司:腾讯实习生

extern是C/C++语言中表明函数和全局变量作用范围(可见性)的关键字,该关键字告诉编译器,其声明的函数和变量可以在本模块或其它模块中使用(只是声明,不分配内存)

与extern对应的关键字是static,被它修饰的全局变量和函数只能在本模块中使用。因此,一个函数或变量只可能被本模块使用时,其不可能被extern “C”修饰。

被extern “C”修饰的变量和函数是按照C语言方式编译和链接的

之所以要如此是因为编译器在将C++ 源代码编译成目标文件时,会将函数和变量的名称进行修饰,形成符号名,目标文件中所使用的符号名就是修饰后名称,所以对于不同函数签名的函数,即使函数名相同,编译器和链接器都认为它们是不同的函数。因此有时候在调用一些库函数的时候,会出现无法链接的情况(因为函数签名不同)所以对于C++ 来说,必须使用extern “C”来声明这些函数。

为什么会有内存泄漏,怎么检测,怎么避免

涉及公司:拼多多实习生

TODO

C++11有哪些新特性

涉及公司:腾讯实习生

TODO

右值引用解决了什么问题

涉及公司:腾讯实习生

TODO

Java相关问题及解答

简述JAVA的GC机制

涉及公司:阿里云实习生

TODO