用new运算符分配内存并初始化

1.分配内存初始化标量类型(如 int 或 double),在类型名后加初始值,并用小括号括起,C++11中也支持大括号。

int * pi = new int (6); 
double * pd = new double (9.99); 
//C++11中, 支持以下写法
int * pi = new int {6}; 
double * pd = new double {9.99};

2.初始化结构或数组,需要使用大括号列表初始化 ,需编译器 支持 C++11

struct where{double x; double y; double z;};
where * one = new where {1.2, 2.2, 3.2};
int * ar = new int [4] {1, 2, 3, 4};

3.使用 delete 释放 new分配的内存 (仅限于常规 new 分配的 堆内存)

delete pi;
delete pd;
delete one;
// 释放数组 记住 加[]
delete [] ar;

4.创建类对象

(1)new创建对象,pTest用来接收对象指针。new申请的对象,则只有调用到delete时才会执行析构函数,如果程序退出而没有执行delete则会造成内存泄漏:

CTest*  pTest = new  CTest();  delete pTest;

(2)不用new,直接使用类定义申明,使用完后不需要手动释放,该类析构函数会自动执行:

CTest  mTest;

(3)使用普通方式创建的类对象,在创建之初就已经分配了内存空间。而类指针,如果未经过对象初始化,则不需要delete释放:

CTest*  pTest = NULL;

new 失败时处理方式

1.常规分配内存,调用构造函数。分配失败时,抛出异常。定义如下:

[tip type=”tip info” ]

void* operator new(std::size_t) throw(std::bad_alloc);

void operator delete(void *) throw();

分配失败则抛出异常std::bad_alloc,不是返回NULL,所以判断返回值是否为NULL是没用的

[/tip]
char *p=new char[size]; //分配失败,不是返回NULL

delete [] p;

2.不抛出异常。分配失败时,返回NULL。定义如下:

[tip type=”tip info” ]

void* operator new(std::size_t,const std::nothrow_t&) throw();

void operator delete(void*) throw();

[/tip]
char *p=new(nothrow) char[size]; //分配失败,是返回NULL
if(NULL==p)

cout<<"alloc failure!"<<endl;

new运算符函数和替换函数

运算符new 和 new [] 分别调用如下函数:

void * operator new(std::size_t);		//use by new
void * operator new [] (std::size_t);		//use by new []

运算符delete 和 delete [] 分别调用如下函数:

void * operator delete(void *);		        //use by delete
void * operator delete [](void *);		//use by delete []

这些函数称为 分配函数 ,位于全局名称空间中。std::size_t 是一个 typedef

举例说明:

int * pi = new int;
//将转换为下面这样
int * pi = new (sizeof(int));

int * pi = new int[40];
//将转换为下面这样
int * pi = new (40 * sizeof(int));

//同样的
delete pi;
//将转换为下面这样
delete (pi);

定位 placement new 运算符

通常,new负责在 堆 中分配一个足以满足要求的内存块,但 定位new可以让程序员指定要使用的内存位置。不会内存分配失败,因为它根本不分配内存,只调用对象的构造函数。它允许在一块已经分配成功的内存上重新构造对象或对象数组。定义如下:

void* operator new(size_t,void*);
void operator delete(void,void);

1.使用 定位new运算符,首先要包含 头文件 new

#include<new>
using namespace std;
struct chaff
{
    char dross[20];
    int slag;
};
char buffer1[50];
char buffer2[200];
int main()
{
    chaff * p1, p2;
    p2 = new (buffer1) chaff;	// 在buffer1中
    p2 = new (buffer2) int[20]; // 在buffer2中
}

2.使用placement new构造起来的对象或数组,要显式调用它们的析构函数来销毁(析构函数并不释放对象的内存),千万不要使用delete.这是因为placement new构造起来的对象或数组大小并不一定等于原来分配的内存大小,使用delete会造成内存泄漏或者之后释放内存时出现运行时错误。

3.当使用new运算符定义一个多维数组变量或数组对象时,它产生一个指向数组第一个元素的指针,返回的类型保持了除最左边维数外的所有维数。