C++面经总结(一)

C++面经总结

问题一:C++this指针是干啥用的?

答:C++中每个类型可以创建多个对象,不同对象中的私有成员变量不同,但是他们共享同一套成员方法。这时候就要引入this指针进行区分,通过this指针就可以区分这个方法现在操作的是哪个对象的成员。

问题二:C++中new和delete,什么时候用new[]申请,可以用delete释放?

答:new和delete是运算符。new的过程中,不光会申请空间,还会构造对象,把对象初始化,在new[]的时候会多申请4个字节用于存储对象的个数;delete不光会释放空间,也会调用析构函数并释放内存。如果是自定义类型,并且提供了析构函数,那么用new[]申请必须用delete[]释放,如果是内置类型,可以用new[]申请,delete 释放。

问题三:C++的static关键字的作用?

答:从面向过程:static可以修饰全局变量,函数还有局部变量。static修饰全局变量和函数时,在符号表中,会把符号的作用域从global变成local,只会在本源文件中可见;static修饰局部变量时,变量内存就会存放在.data,.bss段,有初始化的放在.data段,没有初始化或者初始化为0的放在.bss ,由于在数据段,程序一开始就会开辟空间,在第一次运行到的时候进行初始化并且只会初始化一次,局部变量本身不产生符号,因为局部变量在栈上都是 ebp -偏移量来访问的。

从面向对象:static可以修饰成员变量和方法,修饰成员变量,就从成员私有的变成成员共享的,修饰成员方法也将不再产生this指针。也就是说被static修饰过的成员方法不再需要对象调用,可以直接通过类作用域调用。

问题四:C++的继承的好处?

答:继承是类和类之间的关系。1.代码的复用。2.通过继承,在基类里面给所有派生类可以保留统一的纯虚函数接口,等待派生类进行重写,通过使用多态,可以通过基类的指针访问不同派生类对象的同名覆盖方法。

问题五:C++vector和list的区别?

答:vector底层是一个一维数组,list底层是链表。vector的数据地址是连续的,而list不连续,list节点间靠指针连接。vector有[]运算符,可以进行随机访问,时间复杂度是O(1),但是插入和删除需要把每一个元素都有移动一下,时间复杂度是O(n),所以迭代器进行erase的时候会使迭代器实效。list进行访问的时候需要从头开始遍历,时间复杂度是O(n),但是进行头部和尾部插入删除的时候时间复杂度是O(1),迭代器进行erase的时候迭代器也不会实效。

问题六:map和multimap的区别?

答:map是一个映射表[key-value],底层实现是红黑树,红黑树的每个节点存放的是key值。map是不允许key重复的,而multimap是允许key值重复的。

(准备红黑树)

问题七:怎样会产生内存泄漏?处理内存泄漏的方法?智能指针详述?

答:内存泄漏产生第一种情况:调用了new,但是忘了调用delete。第二种情况:调用了new,也调用了delete,但是业务逻辑导致delete被忽略。

处理内存泄漏的方法主要用到智能指针。

智能指针:()

问题八:C++如何调用C语言函数接口?

答:C和C++生成符号的方式不同,C和C++语言之间的API接口是无法直接调用的,C语言的函数声明必须括在extern"C"{}中。

问题九:C++类的初始化列表?

答:可以指定对象成员变量的初始化方式,尤其是指定成员对象的构造方式。

问题十:C和C++区别?

答:C语言是面向过程的语言,C++是面向对象的语言,所以C++拥有oop语言非常强大的设计模式,比如单例模式,工厂模式和MVC模式。

C++可以完全兼容C语言,在C语言的基础上增加了引用,模板 ,运算符重载,异常处理机制,还拥有一个强大的C++标准模板库STL。

在动态内存管理上,C语言通过malloc和free函数进行堆内存的分配和释放,C++通过new和delete运算符来管理堆内存。

C++还支持带默认值的函数,函数的重载,内联函数等,这些C语言都不支持。

C++比C语言多了一个类,所以作用域比C语言多了一个类作用域,此外C++还支持namespace命名空间。

问题十一:new和malloc的区别?

答:1、malloc是C的库函数,new是运算符重载。

2、malloc按字节开辟内存,new底层也是用malloc开辟,但是还会初始化对象。

3、malloc开辟内存失败,返回nullptr空指针,new开辟失败,抛出bad_alloc类型的异常。

问题十二:STL中迭代器失效问题?

迭代器是不允许一边读一边修改的,

当通过迭代器插入一个元素的时候,所以迭代器实效

当通过迭代器删除一个元素的时候,当前删除位置到最后的所有元素的迭代器都失效了

当迭代器更新容器元素之后,要及时对迭代器进行更新,insert/erase方法都会返回新位置的迭代器

问题十三:编译链接全过程?

分为预编译,编译,汇编,链接四个过程

预编译阶段:不包括#program在内的所有带#的命令处理,例如:#include头文件、#define宏等,处理注释,增加行号。

编译阶段:进行语法分析,语义分析,包括代码的优化,把代码转化成汇编代码。

汇编阶段:会把汇编代码转成机器码,生成二进制可重定向文件。

链接阶段:把编译完成的所有*.o文件和静态库文件链接起来,分成两个步骤。1.所有 *.o文件段的合并,符号表合并后进行符号解析。2.符号的重定向。

问题十四:堆和栈的区别?

堆内存空间远大于栈内存。堆内存要程序员通过malloc/new开辟内存,free/delete释放内存,栈内存是系统自动开辟回收的。函数的运行,是在栈上开辟栈帧,函数的局部变量也是在栈上,通过文件偏移量访问。堆的分配是从低地址到高地址分配,栈是从高地址到低地址分配的。

问题十五:构造函数和析构函数可不可以是虚函数,为什么?

构造函数不可以是虚构函数,析构函数可以是。

构造函数:在派生类构造的时候要先构造基类,如果基类的构造函数是虚函数,又会直接调用派生类的构造函数,这样基类的成员就没办法初始化了,这是肯定不可以的。而且构造函数在构造的时候对象还不存在,对象不存在也没有虚函数指针,没有虚函数指针也不会有虚函数表,也没办法进行多态调用。

析构函数:可以作为虚函数,而是很有必要。如果不是虚函数,基类指针指向派生类对象的时候,使用delete的时候只会调用基类的析构函数,派生类的析构函数就调用不了;如果是虚析构函数的话,就会形成动态绑定,调用派生类的虚函数表,在派生类的虚函数里存放了派生类的析构函数,这样基类和派生类的析构函数都可以被调用。

问题十六:宏和内联函数的区别?

宏是#define,内联inline,宏在预编译阶段处理,inline在编译阶段处理。 宏就是一个字符串的替换操作,内联函数会在函数调用点,通过函数的实参把函数代码直接展开调用。在调试阶段,宏没办法调试,内联函数可以调试。

问题十七:局部变量存在哪里?

局部变量存放在栈上,通过ebp指针偏移访问,不产生符号,存在.text段。

问题十八:什么是纯虚函数?为什么要有纯虚函数?虚函数表存放在哪里?

带有virtual关键字的且置为0的函数是纯虚函数,有纯虚函数的类叫做抽象类(不能实例化对象,可以定义指针和引用)。

纯虚函数一般定义在基类里面,基类不代表事物实体,主要作用是给所有派生类保留一个统一的接口,让派生类进行重写,方便的使用多态机制。因为基类不需要实例化,它的方法也就不指导该怎么去实现。

虚函数表在编译阶段产生,运行时,加载到.rodata段。

问题十九:说一下C++中的const

const定义的是常量,它的编译方式是:编译过程中,把出现常量名字的地方,用常量的值替换。

const还可以定义常成员方法,称为常方法,this指针前也会加一个const,普通对象和常对象就都可以调用了。

问题二十:指针和引用的区别?

从汇编看:指针和引用生成的代码是相同的,引用就是一个指针。定义一个引用就相当于定义了一个指针,然后把引用内存的地址写到这个指针里。当引用变量修改时,会先访问指针里面的地址,返回在这个地址的内存里把值修改。

其次,指针可以不用初始化,通过赋值可以指向任意同类型的内存;但是引用必须初始化,而且一旦引用这块内存,就咋也不能引用其他内存了。所以引用比指针更加安全。

在进行sizeof操作时,sizeof 指针在 32 位系统下永远是 4 个字节,而sizeof引用计算的是它所引用内存的大小。

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值