C++知识总结(二)

1.malloc/free和new/delete的区别

答:malloc/freenew/delete的共同点是:都是从堆上申请空间,并且需要用户手动释放。不同的地方是:

  • malloc和free是函数,newdelete是操作符
  • malloc申请的空间不会初始化,new可以初始化
  • malloc申请空间时,需要手动计算空间大小并传递,new只需在其后跟上空间的类型即可  malloc的返回值为void*, 在使用时必须强转,new不需要,因为new后跟的是空间的类型
  • malloc申请空间失败时,返回的是NULL,因此使用时必须判空,new不需要,但是new需要捕获异常
  • 申请自定义类型对象时,malloc/free只会开辟空间,不会调用构造函数与析构函数,而new在申请空间 后会调用构造函数完成对象的初始化,delete在释放空间前会调用析构函数完成空间中资源的清理

2.operator new与operator delete 函数

new和delete是用户进行动态内存申请和释放的操作符,operator new和operator delete是系统提供的全局函数,new在底层调用operator new全局函数来申请空间,delete 在底层通过operator delete全局函数来释放空间。

3.new和delete的实现原理

内置类型

  • 如果申请的是内置类型的空间,new和malloc,delect和free 基本相似。
  • 不同的地方是:new/delete 申请和释放的是单个元素空间,而new[], delete[] 申请的是连续空间,而且new在申请空间失败时会抛异常,malloc会返回NULL。

自定义类型

  • new的原理:调用operator new函数申请空间,在申请空间上执行构造函数,完成对象的构造
  • delect的原理:在空间上执行析构函数,完成对象中资源的清理工作;调用operator delect函数释放对象的空间
  • new  T[ N ]的原理:调用operator new[] 函数,在 operator new[]中实际调用operator new函数完成N个对象空间的申请,在申请的空间上执行N次构造函数。
  • delect [] 的原理:在释放的空间上执行N次析构函数,完成N个对象中资源的清理,调用operator delect [] 释放空间,实际在operator delect[] 中调用operator delect来释放空间。

3.内存泄漏

  • 什么是内存泄漏:内存泄漏指因为疏忽或错误造成程序未能释放已经不再使用的内存的情况。内存泄漏并不是指内存在物理上的消失,而是应用程序分配某段内存后,因为设计错误,失去了对该段内存的控制,因而造成了内存的浪费。
  • 内存泄漏的分类:堆内存泄漏(通过malloc/calloc/ralloc/new 等从堆上分配的内存没有释放)、系统内存泄漏(使用系统分配的资源,如:套接字,文件描述符,管道等没有释放,导致系统资源的浪费)
  • 内存泄漏的危害:长期运行的程序出现内存泄漏,影响很大,如操作系统、后台服务等等,出现内存泄漏会导致响应越来越慢,最终卡死。
  • 如何避免内存泄漏:良好的代码规范,RAII思想或智能指针,使用内存泄漏工具检测。

4.那些成员只能在初始化列表进行初始化?

  • const修饰的成员变量
  • 引用类型的成员变量
  • 类类型对象,该类没有默认构造函数

注:初始化列表不能对静态成员进行初始化。

5.explicit关键字 

用explicit修饰构造函数,将会禁止单参构造函数的隐式转换

6.如何一次在堆上申请4G的内存?

因为32位的环境下虚拟地址空间的大小只有4g,而光内核空间就需要1g,所以不可能申请得到,只有在64位的环境下才可以实现,只需要把执行环境改为64x即可。

7.STL

STL:C++标准库的重要组成部分,包罗数据结构和算法的软件框架

STL的六大组件:容器,算法,仿函数,迭代器,配接器,空间配置器

8.string类

常见操作:

函数名字功能说明
string ( )构造函数,构造空字符串对象

string (const char *s)

用C-String 来构造string类对象
string  (size_t n,char c)构造n个字符c组成的string类对象
string (const string &s)拷贝构造函数
size()返回字符串有效字符长度
length()返回字符串有效字符长度
capacity()返回空间总大小
empty()检测字符串是否为空串
clear()清空字符串,不改变底层空间大小
reverse()为字符串预留空间,如果扩容不会改变有效元素个数
resize()有效字符串的个数改为n个,多出的空间用字符c填充
begin()   /end   ()begin 获取第一个字符的迭代器,end获取最后一个字符下一个位置的迭代器
rbegin()   /rend   ()rbegin获取最后一个字符下一个位置的迭代器 ,end获取第一个字符的迭代器
push_back()在字符串后尾插字符
append()在字符串后追加字符串/字符
operator +=在字符串后追加字符串str
c_str()返回C格式字符串
find()从字符串pos位置向后找字符c,返回该字符在字符串的位置
rfind()从字符串pos位置向前找字符c,返回该字符在字符串的位置
substr()在字符串pos向后,截取一部分然后返回
erase()

从字符串pos位置开始,截取n个位置,然后将其返回

9.迭代器失效

迭代器失效:迭代器类似指针,迭代器失效即所指向的节点的无效,即该节点被删除了。

后果:被删除节点的迭代器失效,后续迭代器不会失效。对失效的迭代器进行使用,程序崩溃。

什么操作有可能引起失效:删除的操作:如erase,pop_back,pop_front;resize,assign,赋值

10.虚析构函数一般指的是将基类的析构函数声明为虚函数,在定义一个基类指针,其指向对象是一个派生类的时候,通过动态绑定实现在运行的时候确定该指针的指向是派生类,从而在删除对象的时候调用派生类的析构函数,防止内存泄漏。

11.智能指针为什么可以自动释放内存?

因为智能指针本身是一个类(后面也会自己实现一下),当出了类的作用域的时候,类会调用析构函数进行释放资源。所以智能指针的作用原理就是在函数结束时自动释放内存空间,不需要手动释放内存空间。

12.代码崩溃的原因

  1. 内存泄漏
  2. 对空指针指向的内存非法写操作,对空指针指向的内存非法读操作
  3. 除0操作
  4. 大的临时变量或者递归等导致栈溢出
  5. 对只读内存进行写操作
  6. 堆越界写操作
  7. 对已经释放的内存进行写操作

13.vector 和 list 的区别?

vector底层实现是数组;list是双向 链表。

vector支持随机访问,list不支持。

vector是顺序内存,list不是。

vector在中间节点进行插入删除会导致内存拷贝,list不会。

vector一次性分配好内存,不够时才进行2倍扩容;list每次插入新节点都会进行内存申请。

vector随机访问性能好,插入删除性能差;list随机访问性能差,插入删除性能好。

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值