27. 区分内存分配的方式

c++中内存分为5个不同的区

①栈区

栈是一种特殊的数据结构,其存取数据特点为(先进后出,后进先出)。栈区中主要用于存储一些函数的入口地址,函数调用时的实参值以及局部变量。栈区的大小和内存分配由编译器和底层硬件配合完成在函数调用时发挥很大作用,但是程序员不需要关心其的操作(因此起较安全)。

②堆区

堆区主要是用户自由分配内存的区域,new(malloc())与delete(free())运算符都是在操作这块区域。因为堆区中内存的申请和释放都是交给程序员自己完成所以比较危险,容易出错。在程序结束后所有没有释放的区域都会被操作系统自动回收。

③全局/静态存储区

即全局变量和静态变量所在的内存区域。

④常量存储区

即常量所在的内存区域,其内存中的数据一旦初始化就不能被更改。

⑤代码区

顾名思义即为程序代码加载入内存的区域。

28. new/delete与new[ ]/delete[ ]必须配对使用

因为new向堆区动态申请一个对象的空间,delete是动态释放一个对象的内存空间,

而new[ ]是向堆区动态申请对个对象的空间,delete[ ]是动态释放多个对象的内存空间。

实际new [ ]在申请内存的同时还申请了内存保存申请对象的个数,在用delete[ ]时其会去寻找保存的这个对象个数,进行准确释放。

实际new操作基本数据类型对象,因为基本数据类型没有构造和析构函数可以用delete去释放也可以用delete[ ],但是为了规范和增加代码的可读性还是让new与delete配对使用,new[ ]和delete[ ]配对使用。

29. 区分new的三种状态

new实际有三种状态,不要认为自己对new很了解。

①new operator

第一种状态,其不能重载,其永远都会做三件事

//先为对象分配内存
void *memory = operator new (sizeof(对象类型))
//调用构造函数,初始化内存中的对象(当然对于基本数据类型是没有第二步的)
call 构造函数
//返回对象指针
对象类型 * pStr=static_cast<对象类型 *>(momory)

②operator new

第二种状态,第一种状态包含第二种状态(第一步),可以重载。

其会先向堆区寻找空闲内存,如果失败则调用new_hander函数在重复上述操作,直到抛出ball_alloc异常。

③placement new(包含在new头文件中),一般不使用。

30. new内存失败后应该如何处理

c中malloc函数申请内存失败返回一个NULL指针,可以通过检查NULL指针来处理。

c++中new,如果operator new申请内存错误其最终会抛出一个bad_alloc异常,所以这时候应是处理异常而不是检查NULL指针。

检查异常的方法为:

try
{
int* pStr=new int
}
catch(const bad_alloc& e)
{
//异常处理
}
当然在一些较老的编译器中并不支持这种,那便用检查NULL的方法。

31. 了解new_handler的所作所为

在使用operator new失败后其不是直接抛出bad_alloc异常的,其会先调用函数new_handler,这个函数进行一些操作

①使更大的内存块有效,通过在程序开始时分配一块大的内存,当调用new_handler时把其释放,这样在次operator new时就会成功了。

②装载其他的new_handler函数

因为如果当前的new_handler函数不能调用更大的内存供operator new使用,而有new_handler函数可以完成,则会调用set_new_handler函数把当前的new_handler函数换成那个函数。

③抛出bad_alloc异常

④直接调用exit( )或abort()函数结束程序。

当然可以对new_handler函数进行定制,

即利用set_new_handler函数装入新的new_handler函数。

32. 利用工具解决内存泄露

在程序的入口加上:

_CrtSerDbgFlag(	_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG)
| _CRTDBG_LEAK_CHECK_DF )

在程序运行结束时没有释放的内存会显示出来。

也可以通过其他工具进行解决。

33. 小心翼翼的重载operator new和operator delete

对于自定义数据类型,要想让操作符对其操作必须对其进行重载,而operator new很特殊其不需要重载就可以使用。

但是如果想对其进行重载也可以,不过一般不能将其重载为全局函数因为这样会覆盖掉所有new操作默认的operator new,一般在类中对其进行重载。

以为在调用operator new时还无this指针所以其应该重载为static类型而且规定第一个参数为size_t类型

class	A
{
public:
static void* operator new(size_t size)
static void operator delete( void *p)
};

注意重载operator new就必须重载operator delete

34. 用智能指针管理通过new创建的对象

利用智能指针类代替传统指针

auto_ptr智能指针,其包含在memory头文件中。

auto_ptr指向一个new对象,在其生命周期结束时对其所指向资源进行释放,不需要显示的使用delete。

使用方法:auto_ptr<类型> pa(new(类型))

也可以建立一个未指向任何对象的auto_ptr

auto_ptr<int> iPtr;
if(iPtr.get()==0) //不指向任何对象
{
iPtr.reset(new int(2011)) ;指向一个对象
}

也可以利用一个auto_ptr对两一个auto_ptr赋值

auto_ptr<int> iPtr2(iPtr);

这样的话iptr的资源就移交给了iPer2, iper不能再用。

auto_ptr有很多缺点,其不支持动态配置数组,在赋值时会发生权力转移,其不支持stl容器。

所以在boost中的新的智能指针有5种:scoped_ptr,scoped_array,shared_ptr,shared_array,weak_ptr

其智能指针支持stl容器,支持动态配置数组。

使用其要遵循两条规则

①smart_ptr不同于T*

smart_ptr实际是一个类(智能指针类),而T就是一个t类型的指针

所以不能用T
赋值给smatt_ptr

不能用NULL对smart_ptr的变量赋值,应该用其成员函数(因为其实一个类对象)

②不要使用临时的share_ptr对象

临时对象在函数做参数时,因为函数参数处理顺序是随机的,如果先处理其他参数,而这个参数恰好发生异常,则动态指针的临时对象new的指针无法返回,就会产生内存泄漏。

改善c++程序的150个建议(读后总结)-------27-35的更多相关文章

  1. 编写高质量代码_改善C++程序的150个建议 读书笔记

    这几天看了下这本书<编写高质量代码_改善C++程序的150个建议>,觉的蛮有收获的,再次记录下自己以前不清晰的知识点,以供学习. 编写符合标准的main函数 C语言标准规定了main函数的 ...

  2. 改善c++程序的150个建议(读后总结)-------19-26

    19. 明白在c++中如何使用c c++可以兼容c的绝大部分代码,但是还是有一部分不能兼容. c语言的编译器在调用函数时会把函数翻译成 : "_函数名",例如: int nasa( ...

  3. 改善c++程序的150个建议(读后总结)-------12-18

    12.优先使用前置操作符 #include <iostream> using namespace std; class A { private: int num; public: A op ...

  4. 改善c++程序的150个建议(读后总结)-------10-11

    10. 优化结构体中元素的布局 结构体变量所占空间大小并不是其所含类型所占字节数之和,其所占内存字节数涉及到字节对齐. 字节对齐 :变量在内存中储存都是以字节数为单位,每一个字节都有自己的地址,逻辑上 ...

  5. 改善c++程序的150个建议(读后总结)-------0-9

    0. 不要让main 函数返回 void 入口函数main()返回类型应该为 int, 即程序结束时return 0 表示程序正常返回,函数结束时 return -1 值表示程序异常返回, 如果不显式 ...

  6. 改善C++ 程序的150个建议学习之建议7:时刻提防内存溢出

    作为一个程序员,对内存溢出问题肯定不陌生,它已经是软件开发历史上存在了近40年的大难题.在内存空间中,当要表示的数据超出了计算机为该数据分配的空 间范围时,就产生了溢出,而溢出的多余数据则可以作为指令 ...

  7. 编写高质量代码改善C#程序的157个建议——建议150:使用匿名方法、Lambda表达式代替方法

    建议150:使用匿名方法.Lambda表达式代替方法 方法体如果过小(如小于3行),专门为此定义一个方法就会显得过于繁琐.比如: static void SampeMethod() { List< ...

  8. 改善java程序的151个建议

    <编写高质量代码-改善java程序的151个建议> --秦小波 第一章.开发中通用的方法和准则 1.不要在常量和变量中出现易混淆的字母 long a=0l; --> long a=0 ...

  9. 编写高质量代码改善java程序的151个建议——导航开篇

    2014-05-16 09:08 by Jeff Li 前言 系列文章:[传送门] 下个星期度过这几天的奋战,会抓紧java的进阶学习.听过一句话,大哥说过,你一个月前的代码去看下,慘不忍睹是吧.确实 ...

随机推荐

  1. CentOS 7 卸载 OpenJDK 安装 OracleJDK

    查看 JDK 安装版本 java -version java version 1.7.0_51 OpenJDK Runtime Environment ( rhel-2.4.5.5.el7-x86_6 ...

  2. IPFS矿池集群方案详解

    IPFS作为一项分布式存储技术,可以说是web3.0发展的基石.关于IPFS的产业,如存储.技术.矿机.矿池等也发展得非常迅速. 什么是单机挖矿? 单机挖矿就是一台机器就是一个节点,一台机器就完成挖矿 ...

  3. 20182217_刘洪宇 后门原理与实践 EXP2

    1.后门概念 后门就是不经过正常认证流程而访问系统的通道. 哪里有后门呢? 编译器留后门 操作系统留后门 最常见的当然还是应用程序中留后门 还有就是潜伏于操作系统中或伪装为特定应用的专用后门程序. - ...

  4. Golang 基于Prometheus Node_Exporter 开发自定义脚本监控

    Golang 基于Prometheus Node_Exporter 开发自定义脚本监控 公司是今年决定将一些传统应用从虚拟机上迁移到Kubernetes上的,项目多而乱,所以迁移工作进展缓慢,为了建立 ...

  5. TreeMap和HashMap的元素比较

    写在前面的话 2021.04,准备面试和CCF CSP认证的我准备做一套CCF模拟题,然后就有了此篇博客(x 题目:201912-2 回收站报数 题目截图: 第一个想法:读取每个垃圾的位置,存入Tre ...

  6. 前端er必须知道的Git地址及常用工具地址

    商城篇(找工作必练) 开源商城 推荐指数:5星,掌握了它,可以说,今后工作中的各种需求都不是问题,工作1~2年的也可以学习其中的思路(建议收藏). 这是一个集小程序/公众号/app为一体的商城系统,包 ...

  7. C++并发与多线程学习笔记--基本概念和实现

    基本概念 并发 可执行程序.进程.线程 学习心得 并发的实现方法 多进程并发 多线程并发 总结 C++标准库 基本概念 (并发.进程.线程)区分C++初级编程和中高级编程 并发 两个或者更多的任务同时 ...

  8. [贪心]D. 【例题4】国王游戏

    D . [ 例 题 4 ] 国 王 游 戏 D. [例题4]国王游戏 D.[例题4]国王游戏 解析 贪心思想,考虑交换后的值比交换前的小. 然后数据规模用高精度 Code #include <b ...

  9. HTML5本地存储 localStorage操作使用详解

    1.html5几种存储形式 本地存储(localStorage && sessionStorage) 离线缓存(application cache) indexedDB 和 webSQ ...

  10. 使用pr进行视频的剪辑

    本人作为一个经常浪迹在各个小视频的网站的视频界"gai溜子",很是喜欢一些人上传的综艺或者电影的搞笑搞笑小桥段,有的剪辑下来的片段甚至会比我们自己去看还要有意思的多.我认为视频剪辑 ...