C/C++面试题 | 又怎么会 心事密缝绣花鞋针针怨怼
Cobb 730 1

思考一下,这位博主的问题有没有更好的回答? 可以参考的一些面试题

面试问题积累

C函数参数入栈顺序?

参数从右向左入栈,因为c、c++要支持可变参数的函数,从右向左压栈, 最后一个入栈的就是format格式化字符串,ebp+4就能访问到format,就知道里面 有多少个格式化字符,在栈上取多少个参数 void func(const char *format, ...) { } C/C++面试题 | 又怎么会 心事密缝绣花鞋针针怨怼

析构的时候指针类型改变可以吗?

调用析构函数的时候 类型是void类型,指向的是类对象,会正确调用析构函数吗 class String{}; String p = new String(); delete (void)p; => String的析构函数能正常调用吗? 如果p的类型和指向的析构函数类型相同,可以调用析构函数 类型不同,无法匹配到析构函数。

C/C++面试题 | 又怎么会 心事密缝绣花鞋针针怨怼

delete的底层是free实现的

delete p; p->String* String的析构函数 free释放对象自己的内存 delete (void*)p; free(p)只能释放对象的内存

虚函数实现原理

vfptr => vftable(虚函数地址、RTTI信息)runtime type infomation运行时的类型信息 vfptr => vftable => 动态绑定 call eax寄存器

纯虚函数怎么实现的

基类的作用: 1、代码复用 2、使用多态。基类给所有的派生类保留统一的接口 纯虚函数 => 基类 virtual 函数 =0; 派生类里面重写纯虚函数

share_ptr存在什么问题?如何解决的?

交叉引用问题 shared_ptr => 资源1 shared_ptr | | shared_ptr => 资源2 shared_ptr 栈上的智能指针出作用域,2-1=1, 导致资源无法释放,资源泄露

new资源的时候用shared_ptr,其它地方引用的时候用weak_ptr, 因为weak_ptr不会改变资源的引用计数 shared_ptr => 资源1 weak_ptr | | shared_ptr => 资源2 weak_ptr

shared_ptr是把new对象和new对象的引用计数分开申请内存了, 用make_shared可以统一创建对象和引用计数的内存

平时的PC机是大端还是小端 ?大小端的原理?

小端模式 小端:低字节 - 低地址 高字节 - 高地址 大端:低字节 - 高地址 高字节 - 地址值 检测大小端? union Data { char a; int b; }; Data data; data.b = 4; 小端:data.a:4 大端:data.a: 0

指针和引用的区别

汇编指令上,引用和指针是一样的,引用就是通过指针实现的 指针访问指向的内存,必须手动解引用;引用变量相当于自动解引用 指针可以不初始化;引用必须初始化,使用起来更加安全 指针可以通过赋值指向不同的内存;引用一经初始化,只能引用一块内存 指针可以定义多级的指针;引用没有多级的引用,只有左值引用和右值引用

C++的多态实现方式,

C++的多态实现方式,虚函数内部的地址存的基类函数、派生类函数存的地址关系 基类指针指向不同的派生类对象,调用同名覆盖方法(基类和派生类方法的返回值 、函数名、参数列表都相同,然后基类的函数是个virtual虚函数),基类指针指向 哪个派生类对象,就会调用谁的重写方法

基类指针 =》 指向的对象 =》 vfptr =》 vftable =》取虚函数地址

基类 =》基类类型的虚函数表,里面存的是基类虚函数的地址 派生类 =》 派生类类型的虚函数表,里面存储的是从基类继承来的虚函数的地址, 如果派生类重写了该方法,在派生类的虚函数表中把基类的同名方法覆盖掉

C++为什么可以重载

C编译器根据函数名字生成符号;C++编译器根据函数名字+参数列表生成符号 故函数名相同,如果参数列表不同,就称作函数的重载 - 静态的多态

继承:父类成员变量和子类成员变量地址,谁在低地址

父类成员变量在低地址;子类成员变量在高地址

一个类不可以实例化?单例模式?

抽象类不能实例化。一个类只能产生一个对象: 1. 先把构造函数私有化 2. 提供一个static静态方法返回唯一的对象 3. 把拷贝构造函数=delete掉,防止通过拷贝构造产生新对象

c++11了解吗?说说说都有哪些特性?

nullptr =delete =default 构造函数默认实现 右值引用 智能指针 auto_ptr lambda表达式 <= 函数对象 auto <= 自动推导类型 迭代器 vector::iterator map<int, string>::iterator 迭代器的简化foreach遍历 无序关联容器unorderde_set\unorderde_map

一个结构体里面定义了一个char和double,它的空间内存布局是怎么样的

char占一个字节,double占8个字节,在结构体中,根据内存对其原则 选择最长的字节double为对齐方式,char补了7个字节。

有一个函数

string fun(string s1, string s2) { string tmp = s1+s2; return tmp; } 主函数里面通过: string s = fun(s1, s2); 调用, 依照代码执行顺序分析一下调用了什么构造函数和顺序 以及析构函数的调用顺序。 如果我fun函数内写成 return s1 + s2 有什么区别?

实参s2到形参s2的拷贝构造,实参s1到形参s1的拷贝构造 s1和s2右值拷贝构造tmp的, 右值拷贝s, 析构 s、 temp、s1、s2

堆和栈的区别

内存的角度来回答: 栈空间的内存是由系统自动分配,堆空间需手动调用 在C语言中,调用函数malloc free 在C++中, 调用new 和 delete 进行开辟和释放。 其中,容易忘记释放资源或者释放的资源程序未执行到,就发生内存泄露。

栈 高——> 低 扩展的数据结构(先进后出),是连续的内存的区域。 堆 低——> 高 扩展的数据结构,是不连续的内存区域。

何时使用堆和栈? 在定义的空间大小不定,比如: 需要扩容的情况下使用堆。

程序的内存布局。

从低往高 text, rodata, data, bss, 堆,共享库,栈,内核空间

常对象普通的成员方法

常对象,调用普通的成员方法,为什么不让调用? 对象调用方法,实际底层是把对象的地址当作实参传递进去, 常对象的地址是不可能被一个普通的this指针接收的,类型不匹配!

构造函数能被声明为虚函数吗,为什么?

不可以。方法的调用是否依赖对象

  • 构造函数没执行完,对象还没有产生,没办法发生 动态绑定。

析构函数需要被声明为虚函数吗,为什么?

可以。因为析构函数调用时,对象是存在的 什么时候必须实现虚析构函数? 基类指针指向new出来的派生类对象时,delete基类指针, 会造成资源泄漏,因为它只会调用基类的析构,不会派生类 的析构。 delete p; 析构函数调用,发生动态绑定

static方法能不能被声明为虚函数吗,为什么?

不能,因为static方法的调用不依赖于对象, 连对象都没有,不可能找到vfptr,也就不会找vftable, 定义成虚函数没有任何意义

静态与非静态成员函数之间有一个主要的区别。那就是静态成员函数没有this指针。 虚函数依靠vptr和vtable来处理。vptr是一个指针,在类的构造函数中创建生成, 并且只能用this指针来访问它,因为它是类的一个成员,并且vptr指向保存虚函数地址的vtable. 对于静态成员函数,它没有this指针,所以无法访问vptr. 这就是为何static函数不能为virtual. 虚函数的调用关系:this -> vfptr -> vftable ->virtual function

为何static成员函数不能为const函数

当声明一个非静态成员函数为const时,对this指针会有影响。 对于一个Test类中的const修饰的成员函数,this指针相当于Test const *, 而对于非const成员函数,this指针相当于Test *. 而static成员函数没有this指针,所以使用const来修饰static成员函数没有任何意义。 volatile的道理也是如此。

const关键字,const怎么修改

const修饰变量,成为常量 不能作为左值 const可以用在函数调用中,修饰形参变量(指针),只能读,不能修改 const常成员方法,生成的this指针是const Type *this指针

const int a = 10; int p = (int)&a; *p = 20;

C++面向对象的三种特性?(每条详细说说)

封装: 通过访问限定符,把属性(成员变量)隐藏起来,然后提供对外public公有 的成员方法,间接访问私有的成员变量,达到保护成员变量不被外部任意修改的目的 继承: 1.把基类的成员复用起来,方便代码的复用 2.在基类里面定义通用的纯虚函数接口,让派生类进行重写,达到多态调用的目的 多态: 基类指针指向不同的派生类对象,调用同名覆盖方法,指针指向哪个对象,就会调用 哪个派生类对象的方法。设计功能接口时,用基类的指针或者引用来统一接收不同的派生类对象即可 代码简洁、复用能力强,不用给每一个派生类对象都设计函数接口

C++继承和组合

C++继承和组合? 你在实际项目中是怎么使用的?什么情况下使用继承?什么情况下使用组合? 组合:一部分关系的时候 继承:一种关系的时候 线程池里面任务的设计

static关键字的作用?(要全面)怎么实现的?

修饰全局变量、局部变量、普通函数、成员方法、成员变量

inline和宏定义的区别?inline是如何实现的?宏定义是如何实现的?

inline函数的替换是在编译阶段处理的 宏定义的替换是在预编译阶段阶段处理的 处理的时机不同啊!

inline只能修饰函数,宏定义可以定义任意类型的宏名

在函数调用点把函数的代码展开,节省了函数的调用开销;宏定义只做字符串替换

du -h:查看当前目录及其子目录所有可统计的磁盘占用大小 du -hd 1:从当前目录开始算,只统计1层的目录磁盘占用大小

评论区

索引目录