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. GreenDao3.2使用详解(增,删,改,查,升级)

    首先看一下效果图: 项目结构如下图所示: 第一步:在build中添加配置如下: projet 目录下的build.gradle dependencies { classpath 'org.greenr ...

  2. 如何开发一个APP——转自知乎

    作者:简单点链接:https://www.zhihu.com/question/22999185/answer/155469014来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注 ...

  3. .NET 6 Preview 3 发布

    前言 2021/4/8 .NET 6 Preview 3 发布,这个版本的改进大多来自于底层,一起来看看都有什么新特性和改进吧. 库改进 新增值类型作为字典值时更快的处理方法 .NET 6 Previ ...

  4. java正则匹配${xxx} 排除单引号双引号内的内容,前提引号必须成对出现

    public static void main(String[] a) { String wpp = "select 1, ${mark} '``this is, `/message22` ...

  5. 【解决】Could not GET 'https://maven.google.com

    现象 解决方案 1. 由于Google被墙导致的问题 参考 配置阿里云源修改maven的源地址. 2. 由于错误配置代理导致的问题(提示400) 查看工程目录下的gradle.properties和C ...

  6. (二)Struts2配置文件

    一.web.xml文件 web.xml配置文件是一种J2EE配置文件,决定servlet容器的HTTP元素需求如何进行处理.它严格来说不是一个Struts2 配置文件,但它是Struts2 运作所需要 ...

  7. JavaScript深入理解-Set、Map、WeakSet和WeakMap

    Set Set 对象允许储存任何类型的唯一值,无论是原始值或者是对象引用 本质:构造函数,用来生成 Set 数据结构 描述 Set 对象是值的集合,你可以按照插入的顺序迭代它的元素.Set 中的元素只 ...

  8. leetcode 刷题(数组篇)26题 删除有序数组中的重复值 (双指针)

    题目描述 给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度. 不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额 ...

  9. 因为这几个TypeScript代码的坏习惯,同事被罚了500块

    作者:Daniel Bartholomae 翻译:疯狂的技术宅 原文链接:https://startup-cto.net/10-bad-typescript-habits-to-break-this- ...

  10. B1029/A1048 旧键盘损坏了,在输入一段文字时坏了的键不可以正常使用,现给出应输入的一段文字,和实际输出的文字,找出坏掉的键。

    #include<cstdio> #include<cstring> const int maxn = 1000; bool HashTable[maxn] = { false ...