面试准备3

78 阅读6分钟

1:在C++调用中被C编译器编译后的函数,为啥要加extern "C"?

在C++中调用C编译器编译后的函数时,需要使用extern "C"来告诉C++编译器这部分代码是用C语言编写的,而不是C++。这是因为C++支持函数重载,而C语言不支持,因此C++编译器会为函数名添加一些修饰信息以区分重载的函数。如果C++代码直接调用C函数,而不使用extern "C",那么C++编译器可能会因为找不到对应的函数名(由于修饰信息)而报错。

  1. new delete 和 malloc free 的区别?

newdelete是C++中的运算符,用于动态内存分配和释放。它们不仅分配和释放内存,还会调用对象的构造函数和析构函数。而mallocfree是C语言中的函数,只负责分配和释放内存,不会调用构造函数和析构函数。此外,newdelete更安全,因为它们会检查内存分配是否成功,并在分配失败时抛出异常。

  1. C++的内存分配

C++中的内存分配主要分为四个区域:堆区、栈区、全局/静态存储区和代码区。堆区用于动态分配内存,如使用newmalloc分配的内存。栈区用于存放局部变量和函数调用的上下文。全局/静态存储区用于存放全局变量和静态变量。代码区用于存放程序的代码

  1. 构造函数和析构函数可不可以为虚函数,为什么?

构造函数不能为虚函数,因为虚函数是在对象创建后才会生效,而构造函数是在对象创建过程中调用的。但是析构函数可以为虚函数,这样可以确保在删除指向派生类对象的基类指针时,能够正确调用派生类的析构函数,避免内存泄漏。

  1. 什么是死锁? 死锁是指两个或多个进程在无限期地等待一个资源(如内存、CPU、文件等),从而导致它们都无法继续执行。这通常发生在进程之间存在循环等待条件的情况下,即每个进程都在等待另一个进程释放资源,从而形成一个封闭的循环链。死锁会导致系统资源的浪费,甚至可能导致整个系统的崩溃。 5. 怎样解决死锁。 解决死锁的策略主要有以下几种: * 预防死锁:通过破坏死锁发生的四个必要条件(互斥条件、占有并等待条件、不可抢占条件和循环等待条件)来预防死锁的发生。例如,可以采用一次性请求所有资源、按顺序请求资源等方法来避免循环等待条件。 * 避免死锁:通过允许进程动态地申请资源,但在分配资源之前先判断是否会导致死锁,如果会则不分配。这种方法需要系统具有足够的智能来预测未来的资源需求,因此实现起来比较复杂。 * 检测死锁:通过定期检测系统中的进程和资源状态来判断是否发生了死锁,并在检测到死锁时采取措施进行恢复。这种方法需要系统能够实时地监控进程和资源状态,因此会对系统性能产生一定的影响。 * 解除死锁:当检测到死锁时,可以采取一些措施来解除死锁,如抢占资源、撤销进程等。这种方法需要谨慎处理,以免对系统造成更大的影响。

  2. 重载和重写的区别: 函数重载(Overloading)是指在同一作用域内,可以有一组具有相同函数名,不同参数列表的函数,这组函数被称为重载函数。函数重载主要用于实现功能类似但参数不同的函数。而函数重写(Overriding)或称为函数覆盖,是指子类重新定义父类虚函数的方法。重写要求子类函数和父类函数具有相同的函数名、参数列表和返回类型。函数重写主要用于实现子类对父类行为的定制或扩展。

  3. static的用法和作用,以及与const的区别: 在C++中,static关键字有多种用法。它可以用于修饰局部变量,使其只在文件内可见,并延长其生命周期至整个程序执行期间;也可以用于修饰全局变量或函数,限制其作用域为本源文件;还可以用于修饰类成员变量或成员函数,表示它们属于类本身而非类的对象。const关键字用于定义常量,即其值在程序运行期间不能被修改。与static不同,const强调的是值的不可变性。

  4. 动态库和静态库的区别: 动态库和静态库的主要区别在于链接方式和运行时行为。静态库在编译时会被完全嵌入到可执行文件中,因此生成的可执行文件较大,但运行时不需要额外加载库文件。而动态库在编译时只保留对库文件的引用,实际代码在运行时才加载,因此生成的可执行文件较小,但需要依赖外部的库文件。此外,动态库支持多个程序共享同一份库文件,而静态库则每个程序都有自己的一份拷贝。

  5. 虚函数和纯虚函数的区别: 虚函数是在基类中声明为virtual的成员函数,它允许子类重写该函数并实现多态性。子类可以通过重写虚函数来提供自己的实现。而纯虚函数是在基类中声明为=0的成员函数,它没有具体的实现,子类必须提供纯虚函数的实现才能被实例化。纯虚函数主要用于定义接口或抽象类。

  6. 说一下友元函数: 友元函数是C++中一种特殊的函数,它可以访问一个类的私有和保护成员。通过在类定义中声明某个函数为友元函数,我们可以赋予该函数访问类内部成员的权限。友元函数不是类的成员函数,因此它没有this指针。使用友元函数时需要谨慎,因为它破坏了封装性,可能导致代码难以理解和维护。

  7. 说出你了解的排序算法,并说一下它们的复杂度: 我了解的排序算法包括冒泡排序、选择排序、插入排序、快速排序、归并排序等。冒泡排序、选择排序和插入排序的时间复杂度都是O(n^2),适用于小规模数据的排序。快速排序的平均时间复杂度为O(nlogn),但在最坏情况下会退化为O(n^2)。归并排序的时间复杂度始终是O(nlogn),且空间复杂度也为O(n),适用于大规模数据的排序。