269-面经2

在这里插入图片描述

1、C++this指针干什么用的?

  • 1个类型定义的对象都有各自的成员变量,但是是共享一套成员方法,在成员方法里,具体访问谁的成员变量,这个是靠this指针区分的。
  • 1个类型定义了很多对象,都是私有的成员变量,但是共享一套成员方法,在成员方法里面访问谁的成员变量?通过this指针区分。
  • C++的类的普通成员方法在被编译的时候都会多出来一个this指针
    在这里插入图片描述

2、C++的new和delete,什么时候用new[]申请,可以用delete释放?

  • new和delete本质上是一个运算符重载。operator new,operator delete
  • 当我们用new[]来开辟一个数组内存的时候,相应的在释放这个内存的时候得使用delete[]ptr;
  • delete相当于free有两件事情要做:第一个是调用析构函数,第二个是释放内存。
  • 如果是自定义类型而且提供了析构函数,那么用new[]开辟,就一定需要用delete[]ptr释放。
  • delete[]知道是要释放一个数组内存,就要把数组的每个对象进行析构,然后调用析构函数的时候要传入每个对象的起始地址,就要知道这个内存上有多少个对象,需要把ptr指针-4,才能取到这块内存存储了多少个对象的值。
  • 比如说,new Test[10]; 实际上除了开辟10个Test对象的内存,还需要额外开辟4字节的内存,记录开辟对象的个数。new底层调用malloc开辟内存。
  • 其他的情况,都可以用delete释放。

3、C++的static关键字的作用(我从elf结构,链接过程来回答)?

3.1、从面向过程来说

static可以修饰全局变量,函数,局部变量。

static修饰全局变量和函数,本来是整个工程可见,现在变为仅当前文件可见,全局变量或者函数被static修饰以后,在符号表中, 符号的作用域从g(global)变成l(local)了。

局部变量是指令, 本身不产生符号,通过ebp-偏移量 来访问的,加上static修饰局部变量,变成数据段,要产生符号了,local。

static修饰局部变量的话, 这个变量的内存位置就变到.data段(存储初始化且初始化不为0的数据)或者.bss段(存储未初始化或者初始化为0的数据)了。因为在数据段,程序一开始就开辟内存,第一次运行到它才初始化,只初始化1次。

3.2、从面向对象的角度来说

static可以修饰成员变量,也可以修饰成员方法,也可以在成员方法里定义静态的局部变量。
static修饰成员变量,这个成员变量就从对象私有变成对象所共享的。
static修饰成员方法也一样,变成对象共有的,相当于成员方法不再产生this指针,也就是说,这些方法不需要用对象来调用,用类的作用域来调用。

4、C++的继承?

继承(a kind of)是属于类和类之间的关系,类与类之间常见的关系还有 组合(a part of)。

继承有2大好处:

  • 1、代码的复用,通过1个简单的继承,就可以把基类的成员复用到派生类。
  • 2、通过继承,在基类里面给所有派生类可以保留统一的纯虚函数接口,等待派生类进行重写,通过使用多态(基类指针或者引用指向从这个基类派生的不同的派生类对象,这个基类指针或者引用指向谁,就可以访问谁的同名覆盖方法),可以通过基类指针访问不同派生类对象的重写方法(同名覆盖方法)!
  • 只要持有基类的指针,不管这个指针传进来是哪个派生类对象,都可以访问这个派生类对象的同名覆盖方法。
  • 基本上可以做到开闭原则,添加新的功能可以添加一个额外的派生类从基类继承而来,重写基类的纯虚函数接口就可以了。、

5、C++的继承多态

多态:

  • 静多态(编译时期的多态)
  • 动多态(运行时期的多态)

静多态(编译时期的多态): 函数重载和模板。

函数重载: 一个函数名展现出来很多不同的状态,因为参数列表不同,到底是调用哪个函数重载的版本,这个调用点在编译时就要确定的。

模板: 可以通过不同类型的实例化展现出来。用什么类型从模板实例化代码?这个从编译时确定的。

动多态(运行时期的多态): 虚函数 ,指针/引用指向派生类对象

动多态的好处: 是可以用统一的基类指针或者引用通过指向不同的派生类对象,访问不同派生类对象的同名覆盖方法。 我们在写接口时,全部都是基类的指针或者引用就可以,不放具体的派生类。

6、空间配置器

空间配置器allocator: 给容器使用的;

主要作用: 把内存开辟和对象构造分开,把对象析构和内存释放分开。

  • 原本我们使用new,new不仅开辟空间还会构造对象,delete不仅释放空间还对象析构。

我们为什么把它们分开呢?

  • 当我们去初始化1个容器的时候,这些容器理应是空的,底层只有内存,不应该有对象;
  • 如果在容器构造的时候直接new,不仅仅开辟内存还会构造很多无用、我们不需要的对象。
  • 当我们从容器删除元素的时候,只是需要把对象析构掉,并不需要释放对象的内存,那个内存是容器的内存,容器以后还要使用,因此只需要调用析构函数即可!
  • 如果用delete,会把容器底层所有位置上的都当做对象析构掉,还会释放内存!

7、vector 和list的区别

7.1、vector

  • vector是数组,底层是可以2倍扩容的数组,提供的尾部的增加和删除,push_back,pop_back,O(1)的操作。
  • 适合随机访问多的场合(O(1))(优先级队列是基于vector实现的,底层是大根堆),数组在中间这些位置增加或者删除都是时间复杂度O(N)的操作

7.2、list

  • list是循环的双向链表,节点内存不是连续的,每一个节点都是new出来的,适合于增加和删除操作多的场景,首尾增加和删除的时间复杂度都是O(1),其他节点不会改动。

8、map,multimap?

  • map(不允许key重复的):映射表[key-value],底层实现是红黑树(二叉排序树),通过快速找到key,来找到key对应value。
  • multimap(允许key重复的):映射表[key-value],底层实现是红黑树(二叉排序树),通过快速找到key,来找到key对应value。

红黑树: 5个性质,插入3种情况(最多旋转2次),删除(最多旋转3次)4种情况。

9、C++如何防止内存泄露?智能指针详述?

内存泄漏: 分配的堆内存(没有名字,只能用指针来指向)没有释放,也再没有机会释放了,也就是指向堆内存的指针指向其他地方去了,找不着原来的内存,也就没有机会释放。

int *p = new int[10000];
if(xxx)
 return;//运行抛异常了
delete []p;

使用智能指针来防止内存泄漏(智能指针利用栈上对象出作用域自动析构的特点,在智能指针的析构函数就把资源释放了)

unique_ptr pre(new int[100000]);
//不管代码从哪里return,只要出函数栈帧,对象就要析构,在对象析构函数中释放资源

auto_ptr / scoped_ptr / unique_ptr / shared_ptr / weak_ptr

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

liufeng2023

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值