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. 使用Java+NetBeans设计web服务和页面,用Tomcat部署网页

    一 安装NetBeans(自动安装jdk) 二 创建服务器 三 发布服务 一 安装NetBeans(自动安装jdk) 进入oracle的下载界面: http://www.oracle.com/tech ...

  2. QT项目-Chart Themes Example学习(一)

    1.main.cpp #include "themewidget.h" #include <QtWidgets/QApplication> #include <Q ...

  3. Jmeter(四十) - 从入门到精通进阶篇 - Jmeter配置文件的刨根问底 - 中篇(详解教程)

    1.简介 为什么宏哥要对Jmeter的配置文件进行一下讲解了,因为有的童鞋或者小伙伴在测试中遇到一些需要修改配置文件的问题不是很清楚也不是很懂,就算修改了也是模模糊糊的.更有甚者觉得那是禁地神圣不可轻 ...

  4. 一文教你搞懂 Go 中栈操作

    转载请声明出处哦~,本篇文章发布于luozhiyun的博客:https://www.luozhiyun.com/archives/513 本文使用的go的源码15.7 知识点 LInux 进程在内存布 ...

  5. Istio 实践 之 Circuit breakers 断路器 (请求熔断)

    参考: https://blog.51cto.com/14625168/2499406 https://istio.io/latest/zh/docs/tasks/traffic-management ...

  6. 翻译:《实用的Python编程》08_02_Logging

    目录 | 上一节 (8.1 测试) | 下一节 (8.3 调试) 8.2 日志 本节对日志模块(logging module)进行简单的介绍. logging 模块 logging 模块是用于记录诊断 ...

  7. Sql Server Report Service访问服务页面503解决方法

    这个问题可能性比较多,也有多个方案去解决,可以从如下方法里逐个测试 1.打最新的数据库补丁. 2.删除报表服务配置的密钥,重启报表服务. 3.修改报表服务器配置的用户账户为域管理员 4.找到报表服务器 ...

  8. Vulkan移植GpuImage(三)从A到C的滤镜

    前面移植了几个比较复杂的效果后,算是确认了复杂滤镜不会对框架造成比较大的改动,开始从头移植,现已把A到C的所有滤镜用vulkan的ComputeShader实现了,讲一些其中实现的过程. Averag ...

  9. 【笔记】《Redis设计与实现》chapter19 事务

    chapter19 事务 Redis通过MULTI.EXEC.WATCH等命令来实现事务功能 19.1 事务的实现 事务开始 redis> MULTI ok 通过切换客户端状态的flag属性的R ...

  10. HarmonyOS开发者看过来,HDD上海站传递的重要信息都在这里

    4月17日,颇有HarmonyOS年度总结性质的HarmonyOS开发者日活动上海站正式开始. 活动中,华为消费者业务AI与智慧全场景业务部副总裁段孟对HarmonyOS生态建设的最新进展做了发言,并 ...