C++基础语言篇(二)

C++基础语言篇(二)

1、 请你回答一下为什么析构函数必须是虚函数?为什么C++默认的析构函数不是虚函数 考点:虚函数 析构函数
  1. 将可能会被继承的父类的析函数设置为虚函数,可以保证当我们new一个子类对象,然后使用基类指针指向该对象,释放基类指针时可以释放掉子类的空间可以防止内存泄漏
  2. C++默认的析构函数不是虚函数是因为虚函数需要虚函数表和虚表指针,占用额外的内存,而对于不被继承的类会造成浪费
2、 请你说一下函数指针
  1. 函数指针是指向函数的指针

    C在编译时,每一个函数都有一个入口地址,该入口地址就是函数指针所指向的地址。有了指向函数的指针变量后,可用该指针变量调用函数,就如同用指针变量可引用其他类型变量一样,在这些概念上是大体一致的。

  2. 用途

    调用函数和做函数的参数,比如回调函数

3、 请你说一下fork函数
  1. 创建一个当前进程映像一样的进程可以通过fork系统调用
  2. 成功调用fork( )会创建一个新的进程,它几乎与调用fork( )的进程一模一样,这两个进程都会继续运行。在子进程中,成功的fork( )调用会返回0。在父进程中fork( )返回子进程的pid。如果出现错误,fork( )返回一个负值。
  3. 最常见的fork( )用法是创建一个新的进程,然后使用exec( )载入二进制映像,替换当前进程的映像。这种情况下,派生(fork)了新的进程,而这个子进程会执行一个新的二进制可执行文件的映像。这种“派生加执行”的方式是很常见的。
4、 请你说一下C++析构函数的作用
  1. 析构函数与构造函数对应,对象结束生命周期会调用
  2. 析构函数不能重载,不带参数,没有返回值
  3. 如果一个类中有指针,且在使用的过程中动态的申请了内存,那么最好显示构造析构函数在销毁类之前,释放掉申请的内存空间,避免内存泄漏。
  4. 类析构顺序:1)派生类本身的析构函数;2)对象成员析构函数;3)基类析构函数。
5、 静态函数和虚函数的区别
  1. 静态函数在编译的时候就已经确定运行时机,虚函数在运行的时候动态绑定。虚函数因为用了虚函数表机制,调用的时候会增加一次内存开销
6、 重载和覆盖
  1. 两个函数名相同,但是参数列表不同(个数,类型),返回值类型没有要求,在同一作用域中
  2. 重写:子类继承了父类,父类中的函数是虚函数,在子类中重新定义了这个虚函数,这种情况是重写
7、请你说下strcpy和strlen

strcpy是字符串拷贝函数,原型:

char strcpy(char dest, const char *src);

从src逐字节拷贝到dest,直到遇到’\0’结束,因为没有指定长度,可能会导致拷贝越界,造成缓冲区溢出漏洞,安全版本是strncpy函数。
strlen函数是计算字符串长度的函数,返回从开始到’\0’之间的字符个数。

8、请你说一说你理解的虚函数和多态
  1. 多态的实现主要分为静态多态和动态多态,静态多态主要是重载,在编译的时候就已经确定;动态多态是用虚函数机制实现的,在运行期间动态绑定。举个例子:一个父类类型的指针指向一个子类对象时候,使用父类的指针去调用子类中重写了的父类中的虚函数的时候,会调用子类重写过后的函数,在父类中声明为加了virtual关键字的函数,在子类中重写时候不需要加virtual也是虚函数。
  2. 虚函数的实现:在有虚函数的类中,类的最开始部分是一个虚函数表的指针,这个指针指向一个虚函数表,表中放了虚函数的地址,实际的虚函数在代码段(.text)中。当子类继承了父类的时候也会继承其虚函数表,当子类重写父类中虚函数时候,会将其继承到的虚函数表中的地址替换为重新写的函数地址。使用了虚函数,会增加访问内存开销,降低效率。
9、++i和i++

++i要快一点

10、 请你来写个函数在main函数执行前先运行
__attribute((constructor))void before()
{
    printf("before main\n");
}
11、share_ptr的实现
12、 C++里面是怎么定义常量的,放在哪个内存位置

const加上对象类型,常量定义必须初始化。对于局部对象,常量存放在栈区,对于全局对象,常量存放在全局/静态存储区。对于字面值常量,常量存放在常量存储区。

13、 const修饰成员函数的目的是什么
  1. const修饰的成员函数表明函数调用不会对对象做出任何更改,事实上,如果确认不会对对象做更改,就应该为函数加上const限定,这样无论const对象还是普通对象都可以调用该函数。
14、 如果同时定义了两个函数,一个带const,一个不带,会有问题吗?

相当于函数的重载

15、栈空间的最大值

1M,可以调整

16、extern"c"

C++调用C函数需要extern C,因为C语言没有函数重载。

17 、 请你回答一下new/delete与malloc/free的区别是什么

首先,new/delete是C++的关键字,而malloc/free是C语言的库函数,后者使用必须指明申请内存空间的大小,对于类类型的对象,后者不会调用构造函数和析构函数

18、 请你说说你了解的RTTI

资源分配即初始化,用类来管理指针

19、请你说说虚函数表具体是怎样实现运行时多态的?
  1. 子类若重写父类虚函数,虚函数表中,该函数的地址会被替换
  2. 对于存在虚函数的类和对象,在vs中,对象的对象模型的头部存放指向虚函数表的指针,通过该机制来实现多态
20 、 C语言是怎么进行函数调用的

​ 每一个函数调用都会分配一个函数栈,在栈内进行函数的执行过程。调用栈,先把返回地址压栈,然后把当前函数的esp指针压栈

参数的压栈顺序为从右向左

21、C++中如何处理返回值
  1. 如果不是返回一个变量的引用,一定会产生一个临时的变量
  2. 返回值是引用时应该加const
22、 请你回答一下C++中拷贝赋值函数的形参能否进行值传递?

不能,循环拷贝可得了

23、 请你回答一下malloc与new区别

malloc需要给定申请内存的大小,,new不用指定大小,但是会调用构造函数

24、select
  1. select 函数监视的文件描述符分3类,分别是writefds、readfds、和exceptfds。调用后select函数会阻塞,直到有描述副就绪(有数据 可读、可写、或者有except),或者超时(timeout指定等待时间,如果立即返回设为null即可),函数返回。当select函数返回后,可以 通过遍历fdset,来找到就绪的描述符。
  2. 调用select的几大缺点
    • 每次调用select都要将fd集合从用户态拷贝到内核态,这个开销在fd很多时会很大
    • 同时每次调用select都需要在内核遍历传递进来所有的fd,这个开销在fd很多时也很大
    • select支持的文件描述符数量太小了,默认是1024
25、fork,wait,exec函数
  1. 父进程产生子进程使用fork拷贝出来一个父进程的副本,此时只拷贝了父进程的页表,两个进程都读同一块内存,当进程写的时候使用写实拷贝机制分配内存
  2. exex函数可以加载一个elf文件去替换父进程,从此父进程和子进程就可以运行不同的程序了
  3. fork从父进程返回子进程的pid,从子进程返回0.调用了wait的父进程将会发生阻塞,直到有子进程状态改变,执行成功返回0,错误返回-1。exec执行成功则子进程从新的程序开始运行,无返回值,执行失败返回-1
26、静态函数与虚函数的区别
  1. 静态函数在编译就已经确定好运行时机,虚函数在运行的时候动态绑定
  2. 虚函数使用了虚表机制,调用会增加一次内存开销
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值