条款16:成对使用new和delete时,采取相同的形式
来看一个例子:
std::string* stringArray = new std::string[100];
...
delete stringArray;
问题:stringArray所含的100个string对象中的99个可能并没有被适当地删除,因为它们的析构函数很可能没有被调用。
- 内存被分配出来
- 针对此内存会有一个或更多个构造函数被调用
- 针对此内存会有一个或更多个析构函数被调用
- 内存被释放

std::string* stringPtr1 = new std::string;
std::string* stringPtr2 = new std::string[100];
...
delete stringPtr1;
delete[] stringPtr2;
如果对stringPtr1使用delete[]形式,delete会读取若干内存并将它解释为“数组大小”,然后开始多次调用析构函数。这是很危险的,同时编译器是不会帮你检查的。
如果对stringPtr2使用delete形式,这会导致较少的析构函数被调用,这种错误对于内置类型int也是不可以的,虽然这种类型没有析构函数。
所以游戏规则很简单:
当使用typedef时,要变得尤为敏感,因为你必须要明确地知道,这时的new是一个什么样的形式:
typedef std::string AddressLines[4]; // 每个人的地址有4行,每行是一个string,typedef用于掩饰复合类型 // 这时候AddresLines是一个数组,所以new时,应该是[]形式
std:string* pal = new AddresLines; // 相当于:new string[4];
//那么,必须匹配数组形式的delete
delete pal; // error,行为未定义
delete[] pal; // pass
所以,最好尽量不要对数组形式使用typedef动作。
假定指针变量p定义为“int *p=new int(100);”,要释放p所指向的动态内存,应使用语句delete p还是delete[] p。
这个问题很简单,注意int后面是小括号,所以:
1.new int[] 是创建一个int型数组,数组大小是在[]中指定,例如:
int * p = new int[10]; //p执行一个长度为10的int数组。 2. new int()是创建一个int型数,并且用()括号中的数据进行初始化,例如:
int *p = new int(10); // p指向一个值为10的int数。
所以正确的形式是delete p;
使用 char* p = new char[100]申请一段内存,然后使用delete p释放,有什么问题? 不会有内存泄露,但不建议用
当用delete来释放用new int[]申请的内存空间时,由于其为基本数据类型没有析构函数,所以使用delete与delete []相同,两者都会释放申请的内存空间,若是自定义的数据类型,有析构函数时,用new []申请的空间,必须要用delete []来释放,因为要delete []时会逐一调用对象数组的析构函数,然后释放空间。总而言之就是delete某一个指针都能够回收申请的内存空间,但是对于自定义的数据类型,要分别调用每一个对象的析构函数,所以在收回内存空间之前要先挨个的调用析构函数。delete[]的作用就是,先根据前面的n确定有几个对象,然后确定每个对象的边界,依次调用它们的析构函数。
条款16:成对使用new和delete时,采取相同的形式的更多相关文章
- Effective C++(16) 成对使用new和delete时要采取相同的形式
问题聚焦: 我们都知道,new和delete要成对使用,但是有时候,事情往往不是按我们预期的那样发展. 对于单一对象和对象数组,我们要分开考虑 遇到typedef时,也需要 ...
- 读书笔记 effective c++ Item 16 成对使用new和delete时要用相同的形式
1. 一个错误释放内存的例子 下面的场景会有什么错? std::]; ... delete stringArray 一切看上去都是有序的.new匹配了一个delete.但有一些地方确实是错了.程序的行 ...
- Effective C++ -----条款16:成对使用new和delete时要采取相同形式
如果你在new表达式中使用[],必须在相应的delete表达式中也使用[].如果你在new表达式中不使用[],一定不要在相应的delete表达式中使用[].
- 条款16:成对使用new和delete时要采取相同形式
NOTE: 1.如果你在new表达式中使用[],必须在相应的delete表达式中也使用[].如果你在new表达式中不使用[],一定不要在相应的delete表达式中使用[].
- 【16】成对使用new和delete时要采取相同形式
简而言之,new时不带[],delete时也不带[]:new时带[],delete时也要带[].如果不匹配,要么造成多销毁对象,导致未定义行为:要么导致少销毁对象,导致内存泄漏.
- [Effective C++ --016]成对使用New和Delete时要采用相同形式
这一节比较简单,可以总结为以下: std::string *stringPtr1 = new std::string; std::]; .. delete stringPtr1; // delete ...
- 条款16:成对使用new和delete时要使用相同的形式
请牢记: 如果在new表达式中使用[],必须在相应的delete表达式中也使用[]. new[] 对应 delete[] 如歌在new表达式中不适用[],一定不要在相应的delete表达式中使用[ ...
- 条款五:对应的new和delete要采用相同的形式
string *stringarray = new string[100]; ... delete stringarray; 上述程序的运行情况将是不可预测的.至少,stringarray指向的100 ...
- 条款16:成对使用 new和delete时要采取相同的形式
std::string* stringPtr1=new std::string; srd::string* stringPtr2=new std::string[100]; 对应地 delete也 ...
随机推荐
- C语言入门(11)——switch分支语句
C语言提供了一种用于多分支选择的switch语句, 其一般形式为: switch(表达式) { case 常量表达式1:语句1; break; case 常量表达式2:语句2; break; .... ...
- 清风注解-Swift程序设计语言:Point1~5
目录索引 清风注解-Swift程序设计语言 Point 1. Swift 风格的"Hello, world" 代码事例: println("Hello, world&qu ...
- VC6.0调试大全
VC调试方法大全 一.调试基础 调试快捷键 F5: 开始调试 Shift+F5: 停止调试 F10: 调试到下一句,这里是单步跟踪 F11: 调试到下一句,跟进函数内部 Shift+F11: ...
- 解决Android中TextView首行缩进的问题
方式一:(推荐) setText("\u3000\u3000"+xxxxx); 方式二:这种方式不同分辨率会有问题 setText(""+xxxxx); 半角: ...
- asp.net 向后台提交 html 代码段 包括 <> 标签
首先 在默认情况向标签类的东西是不会让你提交的 这是出于.net 的默认安全机制 我们要先在 <%@ page %> 里边加上 ValidateRequest="false&q ...
- 阿里P8分享:关于做事方式与做事态度
转载:http://www.neitui.me/y/1019 阿里P8分享:关于做事方式与做事态度贴图1: 贴图2: 贴图3:
- headfirst之装饰模式
class A A.hello class B extends A B.hello = A.hello+B 装饰模式:子类对父类想要包装的方法进行重写,使之成为加强版
- FAT下的winhex数据恢复
一·我在自己的U盘中建一个一个文件abc.word,然后删除 二·用winhex打开需要恢复的磁盘 我这是U盘 I:按确定打开它 三.来到它的根目录下 四·查找文件名,找到文件目录项 文件起始簇号:5 ...
- Mysql 如何做双机热备和负载均衡 (方法一)
MySQL数据库没有增量备份的机制,但它提供了一种主从备份的机制,就是把主数据库的所有的数据同时写到备份数据库中.实现MySQL数据库的热备份. 下面是具体的主从热备份的步骤:假设主服务器A(mast ...
- 3种方式实现可滑动的Tab
1. 第一种,使用 TabHost + ViewPager 实现 该方法会有一个Bug,当设置tabHost.setCurrentTab()为0时,ViewPager不显示(准确的说是加载),只有点击 ...