C++中的 new / delete
new的3种形态: new operator , operator new , placement new
1.new operator: new操作符,像 + - * / && . :: ?: 等操作符一样,是语言内置的, 它 不能被重载,不能改变其行为。 它的行为包括分配内存的 operator new 和调用构造函数的 placement new。 new operator 实际上做了三件事:获得一块内存空间、调用构造函数、返回 正确的指针。如果创建的是简单类型(如char)的变量,那么第二步会被省略。
比如: CTest* pT = new CTest(1, 2);
它的调用实际上等效于:
void* p = operator new( sizeof(CTest) );
CTest* pT = new(p) CTest(2, 2);
其中前一句是operator new分配内存,后一句是placement new调用构造函 数,并返回正确的CTest*指针。
2.operator new: 操作符new,原型为: void* operator new(size_t size); 它分配指定大小的内存, 可以被重载, 可以添加额外的参数, 但第一个参数 必须为 size_t 。 它除了被 new operator 调用外也可以直接被调用, 如: void* p = operator new(sizeof(CTest)); 这种用法和调用 malloc 一样, 只分配了sizeof(CTest)大小的内存。
3.placement new: 置换new,它在一块指定的内存上调用构造函数, 包含头文件<new>之后也可 以直接使用,如: CTest* pT = new(p) CTest(2, 2); 他在p这块内存上调用CTest的构造函数来初始化CTest。 如果用 placement new 构造出来的对象,必须显示的调用对象的析构函数, 如: pT->~CTest(); 然后释放能存, 调用 operator delete (对应于分配时的 operator new) operator delete(pT); delete operator: delete操作符,和 new operator 一样,不能被重载,不能改变其行为。 delete operator 做的事有:调用析构函数,然后调用operator delete来 释放内存,比如: delete pT; 它的调用实际上等效于: pT->~CTest(); operator delete(pT); operator delete: 同理,对应于分配内存的 operator new,释放内存的为 operator delete , 它也可以被重载。 operator new [] operator delete [] 也是同样原理 ....
new 的基本使用指南
1)、想在堆上建立一个对象,应该用 new 操作符,它既分配内存又为对象调用构 造函数。
2)、如果仅仅想分配内存,就应该调用 operator new 函数;它不会调用构造函数。
3)、如果想定制在堆对象被建立时的内存分配过程,应该重载 operator new 函数, 然后使用 new operator,new operator 会调用定制的 operator new 。 4)、如果想在一块已经获得指针的内存里建立一个对象,应该用 placement new 。 placement new 主要适用于:
(a): 对时间要求非常高的应用程序中,因为这些程序分配的时间是确定的;
(b): 长时间运行而不被打断的程序;
(c): 以及执行一个垃圾收集器 (garbage collector) 。
注意:如果用 placement new 构造出来的对象,必须显示的调用对象的析构函数。
如上所述,调用 delete pT; 的执行可以看作如下这样一个过程:
pT->~CTest();
operator delete(pT); 其中: pT->~CTest() 语句调用析构函数。(析构函数本身是不会释放内存的) operator delete(pT) 释放内存。 (这是一个对象在消亡之前的最后动作) 若CTest类重载了operator delete(), 那么将不调用全局的operator delete(pT), 而是调用 pT->operator delete(pT)(在CTest::operator delete()内最好还应该调用 全局的operator delete来释放内存)。
问:成员函数调用 delete this 合法吗? 答:只要你小心,一个对象请求自杀(delete this),是可以的! 以下是对 "小心" 的定义:
1)、必须100%的确定:对象是用 new 分配的(不是用new[],也不是用 placement new,也不是一个栈上的局部对象,也不是全局的,也不 是另一个对象的成员,而是明白的普通的 new )。
2)、必须100%的确定:该成员函数是对象最后调用的的成员函数。
3)、必须100%的确定:该成员函数在 delete this 之后的代码中不接触到 对象的任何一块(包括调用任何其他成员函数或访问任何数据成员)。
4)、必须100%的确定:在 delete this 之后不再去访问this指针。你不能 去检查它,将它和其他指针比较,和NULL比较,打印它,转换它..., 不能对它做任何事。
自然,对于这种情况还要习惯性地告诫:当你的指针是一个指向基类类 型的指针,而没有虚析构函数时(也不可以delete this)。因为是在类 成员函数里面delete this的,所以在此语句以后,不能访问任何成员变 量及虚函数(调用虚函数必须对象实例存在以检查类型),否则一定非法。 上面所说的情况,在执行时不一定会报错,但尽量不要这么做。因为,一般来 说,内存释放释放的只能是数据段的内容(包括堆和栈,但释放栈上的内存由系统 进行),而代码段的内存在内存中是永远不会释放/改变的,直到程序结束。因此 在内存释放后也是可以访问的。所以,一般所谓的释放内存delete操作,是在数据 段进行的释放。但是,并不要因为这样,就违背上面的原则。
new 应用实例
/* F1 中的 new operator,他的行为就像F2中的 operator new 和 placement new 一样, 也可以用F3中的方法达到相同的效果。 */
#include <new>
#include <stdio.h>
class CTest {
public:
CTest(int _x, int _y) { X = _x; Y = _y; }
~CTest() { X = ; Y = ; }
void Test(char* sz) { printf("%s: X=%d Y=%d \n", sz, X, Y); }
int X; int Y;
}; /* new operator: */
void F1() {
CTest* pT = new CTest(, ); // new operator
pT->Test("F1");
delete pT;
} /* operator new placement new */
void F2() {
void* p = operator new(sizeof(CTest)); // operator new : 分配内存
CTest* pT = new(p) CTest(, ); // placement new: 构造对象
pT->Test("F2");
pT->~CTest(); // 必须显示析构对象
operator delete(pT); // operator delete: 释放内存
}
/* 也可这样实现: */
void F3() {
char* p = new char[sizeof(CTest)]; // new operator: char为内置类型,不会调用构造函数,相当于只分配内存
CTest* pT = new(p) CTest(, ); // placement new: 在这块内存上构造CTest对象
pT->Test("F3");
pT->~CTest(); // 必须显示析构CTest对象
delete [] p; // delete operator: char为内置类型,不会调用析构函数,相当于只释放内存
}
void main()
{
F1();
F2();
F3();
}
本文参考百度文库一篇文章,如有侵权,请联系我!
C++中的 new / delete的更多相关文章
- 数据库设计中的Soft Delete模式
最近几天有点忙,所以我们今天来一篇短的,简单地介绍一下数据库设计中的一种模式——Soft Delete. 可以说,该模式毁誉参半,甚至有非常多的人认为该模式是一个Anti-Pattern.因此在本篇文 ...
- c++中new和delete的使用方法
c++中new和delete的使用方法 new和delete运算符用于动态分配和撤销内存的运算符 new用法: 1. 开辟单变量地址空间 1)new int; //开辟一个存放数组的存储空间 ...
- C++中的new/delete与operator new/operator delete
new operator/delete operator就是new和delete操作符,而operator new/operator delete是函数. new operator(1)调用opera ...
- oracle中drop、delete和truncate的区别
oracle中drop.delete和truncate的区别 oracle中可以使用drop.delete和truncate三个命令来删除数据库中的表,网上有许多文章和教程专门讲解了它们之间的异同,我 ...
- C++中的new/delete
不同于C语言中的malloc/free是库函数,C++语言中的new/delete是运算符,而不是库函数. new/delete执行流程 我们经常会接触到的是new/delete operator(就 ...
- 数据库中drop、delete与truncate的区别
数据库中drop.delete与truncate的区别 drop直接删掉表: truncate删除表中数据,再插入时自增长id又从1开始 :delete删除表中数据,可以加where字句. (1) D ...
- SQL server触发器中 update insert delete 分别给写个例子被。
SQL server触发器中 update insert delete 分别给写个例子以及解释下例子的作用和意思被, 万分感谢!!!! 主要想知道下各个语句的书写规范. INSERT: 表1 (ID, ...
- java中File的delete()方法删除文件失败的原因
java中File的delete()方法删除文件失败的原因 学习了:http://hujinfan.iteye.com/blog/1266387 的确是忘记关闭了: 引用原文膜拜一下: 一般来说 ja ...
- SQL语句的使用,SELECT - 从数据库表中获取数据 UPDATE - 更新数据库表中的数据 DELETE - 从数据库表中删除数据 INSERT INTO - 向数据库表中插入数据
SQL DML 和 DDL 可以把 SQL 分为两个部分:数据操作语言 (DML) 和 数据定义语言 (DDL). SQL (结构化查询语言)是用于执行查询的语法. 但是 SQL 语言也包含用于更新. ...
- 浅谈 C++ 中的 new/delete 和 new[]/delete[]
在 C++ 中,你也许经常使用 new 和 delete 来动态申请和释放内存,但你可曾想过以下问题呢? new 和 delete 是函数吗? new [] 和 delete [] 又是什么?什么时候 ...
随机推荐
- spring aop 如何切面到mvc 的controller--转载
原文:http://yjian84.iteye.com/blog/1920787 网上搜罗半天,不知道什么原因,看了源码,好像他们说的controller 是不受代理的,也对哈,不知道怎么办,于是在h ...
- apache配置php
第一部分:安装apache 1 .安装apache软件,custom 选全部,安装目录为: F:\Apache2.2\ 2.默认为80端口(如冲突,要学会修改端口) 输入:http://localho ...
- Android 中 SQLite 性能优化
数据库是应用开发中常用的技术,在Android应用中也不例外.Android默认使用了SQLite数据库,在应用程序开发中,我们使用最多的无外乎增删改查.纵使操作简单,也有可能出现查找数据缓慢,插入数 ...
- Raphaël.js学习笔记
Rapheal.js 是一个矢量图绘图库.对于支持HTML5 SVG的浏览器使用SVG绘图,不支持SVG的IE(ie6,7,8)使用VML绘图.所以Raphael.js的兼容性非常好. Raphael ...
- 10.5 noip模拟试题
2bc*cosA=b^2+c^2-a^2 数学题QAQ 开始π精度不够40分 怪我喽~ #include<iostream> #include<cstdio> #include ...
- 解决c#处理excel时故障 找不到可安装的 isam
直接拷贝的以前代码,但因软件版本,系统环境的变化,导致提示“找不到可安装的 isam”. 我目前新的软件环境:win8.1+office2010+vs2013 解决办法是修改连接字符串: 处理exce ...
- java 更改list 某一元素?
if(!elTd.getElementsByTag("p").isEmpty()){ int i=eduList.size(); if(i>0){ ...
- 关于@property()的那些属性及ARC简介【nonatomic,atomic,assign,retain,strong,weak,copy。】
@property()常用的属性有:nonatomic,atomic,assign,retain,strong,weak,copy. 其中atomic和nonatomic用来决定编译器生成的gette ...
- 嵌入式css样式,写在当前的文件中
现在有一任务,把下面的“超酷的互联网”.“服务及时贴心”.“有趣易学”这三个短词文字字号修改为18px. 如果用内联式css样式的方法进行设置将是一件很头疼的事情(为每一个<span>标签 ...
- Linux通配符
* 任意字符 ?任意单个字符 [] 匹配指定 字符范围内的字符 [^] 指定范围之外的单个字符 常规字符集合 [a-z] a到z的所有小写字母 [A-Z] a到z的所有大写字母 [0-9] 0到9的所 ...