前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >C++面试题

C++面试题

作者头像
帅地
发布2021-08-25 10:34:41
9780
发布2021-08-25 10:34:41
举报
文章被收录于专栏:苦逼的码农苦逼的码农

大家好,我是帅地。

上次我更新了一整套 Java 面试题,没看过的可以我个人网站看:www.iamshuaidi.com。

也有一些人来催我更新 C++ 的面试题,刚好在正值校招,所以最近也在整理 C++ 的面试题,不过目前只整理的几十道,因为网上的面试题参差不齐,找起来不是很好找。

不过帅地会争取在这一个月内找齐的,方便大家复习,更多面试题可以看文末。

1、new/delete和malloc/free之间有什么关系?

  • 相同点:
    • 对于内部数据类型来说,没有构造与析构的过程,所以两者是等价的,都可以用于申请动态内存和释放内存;
  • 不同点:
    • new/delete可以调用对象的构造函数和析构函数,属于运算符,在编译器权限之内;
    • malloc/free仅用于内存分配和释放,属于库函数,不在编译器权限之内;
    • new是类型安全的,而malloc返回的数据类型是void *,所以要显式地进行类型转换;
    • new可以自动计算所需字节数,而malloc需要手动计算;
    • new申请内存失败时抛出bad_malloc异常,而malloc返回空指针。

2、delete与delete []有什么区别?

对于简单类型来说,使用new分配后,不管是数组数组还是非数组形式,两种方式都可以释放内存:

代码语言:javascript
复制
int *a = new int(1);
delete a;
int *b = new int(2);
delete [] b;
int *c = new int[11];
delete c;
int *d = new int[12];
delete [] d;

对于自定义类型来说,就需要对于单个对象使用delete,对于对象数组使用delete [],逐个调用数组中对象的析构函数,从而释放所有内存;

如果反过来使用,即对于单个对象使用delete [],对于对象数组使用delete,其行为是未定义的;

所以,最恰当的方式就是如果用了new,就用delete;如果用了new [],就用delete []

3、内存块太小导致mallocnew返回空指针,该怎么处理?

对于malloc来说,需要判断其是否返回空指针,如果是则马上用return语句终止该函数或者exit终止该程序;

对于new来说,默认抛出异常,所以可以使用try...catch...代码块的方式:

代码语言:javascript
复制
try {
    int *ptr = new int[10000000];
} catch(bad_alloc &memExp) {
    cerr << memExp.what() << endl;
}

还可以使用set_new_handler函数的方式:

代码语言:javascript
复制
void no_more_memory() {
    cerr << "Unable to satisfy request for memory" << endl;
    abort();
}
int main() {
    set_new_handler(no_more_memory);
    int *ptr = new int[10000000];
}

在这种方式里,如果new不能满足内存分配请求,no_more_memory会被反复调用,所以new_handler函数必须完成以下事情:

  • 让更多内存可被使用:可以在程序一开始执行就分配一大块内存,之后当new_handler第一次被调用,就将这些内存释放还给程序使用;
  • 卸除new_handler:返回空指针,这样new就会抛出异常;
  • 调用abortexit

4、内存泄漏的场景有哪些?如何判断内存泄漏?如何定位内存泄漏?

内存泄漏的场景:

mallocfree未成对出现;new/new []delete/delete []未成对出现;

  • 在堆中创建对象分配内存,但未显式释放内存;比如,通过局部分配的内存,未在调用者函数体内释放: char* getMemory() { char *p = (char *)malloc(30); return p; } int main() { char *p = getMemory(); return 0; }

未定义拷贝构造函数或未重载赋值运算符,从而造成两次释放相同内存的做法;比如,类中包含指针成员变量,在未定义拷贝构造函数或未重载赋值运算符的情况下,编译器会调用默认的拷贝构造函数或赋值运算符,以逐个成员拷贝的方式来复制指针成员变量,使得两个对象包含指向同一内存空间的指针,那么在释放第一个对象时,析构函数释放该指针指向的内存空间,在释放第二个对象时,析构函数就会释放同一内存空间,这样的行为是错误的;

没有将基类的析构函数定义为虚函数。

判断和定位内存泄漏的方法:在Linux系统下,可以使用valgrind、mtrace等内存泄漏检测工具。

5、内存的分配方式有几种?

  • 在栈上分配:在执行函数时,局部变量的内存都可以在栈上分配,函数结束时会自动释放;栈内存的分配运算内置于处理器的指令集中,效率很高,但分配的内存容量有限;
  • 从堆上分配:由new分配/delete释放的内存块,也称为动态内存分配,程序员自行申请和释放内存,使用灵活;
  • 从自由存储区分配:由malloc分配/free释放的内存块,与堆类似;
  • 从常量存储区分配:特殊的存储区,存放的是常量,不可修改;
  • 从全局/静态存储区分配:编译期间分配内存,整个程序运行期间都存在,如全局变量、静态变量等。

6、堆和栈有什么区别?

  • 分配和管理方式不同:
    • 堆是动态分配的,其空间的分配和释放都由程序员控制;
    • 栈是由编译器自动管理的,其分配方式有两种:静态分配由编译器完成,比如局部变量的分配;动态分配由alloca()函数进行分配,但是会由编译器释放;
  • 产生碎片不同:
    • 对堆来说,频繁使用new/delete或者malloc/free会造成内存空间的不连续,产生大量碎片,是程序效率降低;
    • 对栈来说,不存在碎片问题,因为栈具有先进后出的特性;
  • 生长方向不同:
    • 堆是向着内存地址增加的方向增长的,从内存的低地址向高地址方向增长;
    • 栈是向着内存地址减小的方向增长的,从内存的高地址向低地址方向增长;
  • 申请大小限制不同:
    • 栈顶和栈底是预设好的,大小固定;
    • 堆是不连续的内存区域,其大小可以灵活调整

7、静态内存分配和动态内存分配有什么区别?

  • 静态内存分配是在编译时期完成的,不占用CPU资源;动态内存分配是在运行时期完成的,分配和释放需要占用CPU资源;
  • 静态内存分配是在栈上分配的;动态内存分配是在堆上分配的;
  • 静态内存分配不需要指针或引用类型的支持;动态内存分配需要;
  • 静态内存分配是按计划分配的,在编译前确定内存块的大小;动态内存分配是按需要分配的;
  • 静态内存分配是把内存的控制权交给了编译器;动态内存分配是把内存的控制权给了程序员;
  • 静态内存分配的运行效率比动态内存分配高,动态内存分配不当可能造成内存泄漏。

8、如何构造一个类,使得只能在堆上或只能在栈上分配内存?

  • 只能在堆上分配内存:将析构函数声明为private
  • 只能在栈上生成对象:将newdelete重载为private

9、浅拷贝和深拷贝有什么区别?

浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享一块内存;而深拷贝会创造一个相同的对象,新对象与原对象不共享内存,修改新对象不会影响原对象。

10、字节对齐的原则是什么?

  • 从偏移为0的位置开始存储;
  • 如果没有定义#pragma pack(n)
    • sizeof的最终结果必然是结构内部最大成员的整数倍,不够补齐;
    • 结构内部各个成员的首地址必然是自身大小的整数倍;
  • 如果定义了#pragma pack(n)
    • sizeof的最终结果必然必然是min[n,结构内部最大成员]的整数倍,不够补齐;
    • 结构内部各个成员的首地址必然是min[n,自身大小]的整数倍。

由于公众号没有目录,阅读体验可能不大好,所以呢,更多面试题可以在我个人网站阅读哦。 C++面试题:https://www.iamshuaidi.com/2309.html

ps:点击阅读原文可直达,不过建议PC端阅读

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-08-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 帅地玩编程 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1、new/delete和malloc/free之间有什么关系?
  • 2、delete与delete []有什么区别?
  • 3、内存块太小导致malloc和new返回空指针,该怎么处理?
  • 4、内存泄漏的场景有哪些?如何判断内存泄漏?如何定位内存泄漏?
  • 5、内存的分配方式有几种?
  • 6、堆和栈有什么区别?
  • 7、静态内存分配和动态内存分配有什么区别?
  • 8、如何构造一个类,使得只能在堆上或只能在栈上分配内存?
  • 9、浅拷贝和深拷贝有什么区别?
  • 10、字节对齐的原则是什么?
相关产品与服务
检测工具
域名服务检测工具(Detection Tools)提供了全面的智能化域名诊断,包括Whois、DNS生效等特性检测,同时提供SSL证书相关特性检测,保障您的域名和网站健康。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档