您的位置:首页 > 编程语言 > C语言/C++

c++中new和delete的使用方法

2012-11-03 20:35 288 查看
摘自:/article/5424195.html

new和delete运算符用于动态分配和撤销内存的运算符

new用法:

1. 开辟单变量地址空间

1)new int; //开辟一个存放数组的存储空间,返回一个指向该存储空间的地址.int *a = new int 即为将一个int类型的地址赋值给整型指针a.

2)int *a = new int(5) 作用同上,但是同时将整数赋值为5

2. 开辟数组空间

一维: int *a = new int[100];开辟一个大小为100的整型数组空间

二维: int **a = new int[5][6]

三维及其以上:依此类推.

一般用法: new 类型 [初值]

delete用法:

1. int *a = new int;

delete a; //释放单个int的空间

2.int *a = new int[5];

delete [] a; //释放int数组空间

要访问new所开辟的结构体空间,无法直接通过变量名进行,只能通过赋值的指针进行访问.

用new和delete可以动态开辟,撤销地址空间.在编程序时,若用完一个变量(一般是暂时存储的数组),下次需要再用,但却又想省去重新初始化的功夫,可以在每次开始使用时开辟一个空间,在用完后撤销它.

---------------------------------------------------------------------------------------------
Follow the another relative
---------------------------------------------------------------------------------------------

/*****************************************************************************/

/* C++中的 new / delete */

/*****************************************************************************/

/*

new的3种形态: new operator , operator new , placement new
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*指针。

operator new:

操作符new,原型为:

void* operator new(size_t size);

它分配指定大小的内存, 可以被重载, 可以添加额外的参数, 但第一个参数

必须为 size_t 。

它除了被 new operator 调用外也可以直接被调用, 如:

void* p = operator new(sizeof(CTest));

这种用法和调用 malloc 一样, 只分配了sizeof(CTest)大小的内存。

placement new:

置换new,原型为:

void operator new(size_t size,void*p);

它在一块指定的内存上调用构造函数, 包含头文件<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:

操作符delete,原型为:

void*operator delete(void *p)

同理,对应于分配内存的 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 this */

/*****************************************************************************/

/*

如上所述,调用 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 = 0;

Y = 0;

}

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(1, 1); // 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(2, 2); // 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(3, 3); // placement new: 在这块内存上构造CTest对象

pT->Test("F3");

pT->~CTest(); // 必须显示析构CTest对象

delete [] p; // delete operator: char为内置类型,不会调用析构函数,相当于只释放内存

}

void main()

{

F1();

F2();

F3();

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: