C++ new

new

new,是C++提供的用于动态申请存储空间的 运算符

一、new的使用。

new+数据类型(初值),返回值为申请空间的对应数据类型的地址。

1.使用new申请一个对象

类型或类 * p=new 类型或类
例:int *p = new int(10);//申请了一个初值为10的整型数据
Date*  birthDate= new Date(inityear,initmonth,initday);
--Date为类;

2.使用new申请数组

• new 类型[]{初始化列表}
• 和定义自动变量类似。没有初始化列表 调用无参构造(默认构造一般是不确定 值);常数初始化列表,后面补零;长 度小于初始化序列长度,抛出异常而不是NULL
• 返回该类型的指针
int *arr = new int[10];//申请了能存放10个整型数据元素的数组,其首地址为arr

二、delete运算符的使用。

new运算符通常搭配delete元素安抚来使用,new用来动态申请存储空间,delete用于释放new申请的空间。
语法格式如下:
delete p;
delete birthDate;
delete[] arr;//注意要删除数组时,需要加[],以表示arr为数组。
◼ 如果动态分配了一个数组,但是却用delete p的方式释放,没有用[],则编译时 没有问题,运行时也一般不会发生错误,但实际上会导致动态分配的数组没有被完全释放。
◼ delete释放的是指针所指对象占据的内存。
◼ delete一般的指针(int*,char* ),指针会重新指向一个未知区域,成为一个野指针,但指针已无效(重复释放 将出错)。
◼ delete对象指针,对象指针 保留原本的地址,会调用该对象的析构函数。
但是,delete指针后,给指针赋NULL,是一个好习惯

三、new和malloc的区别。

1.new是一个运算符,在标准库函数中就有,不需要导入头文件。
malloc函数封装在头文件<malloc.h>中,要使用必须先导入头文件。
2.使用malloc函数,必须用sizeof运算符给出申请空间的大小。 new运算符则会自动计算出所需要申请空间的大小。
3.malloc返回值通常需要进行强制类型转化。 new运算符则可以直接返回对应数据类型的地址。

四、二维数组的创建

1. 直接创建

C++ 使用 new 创建二维数组最直接的方法就是 new T[M][N]。返回的指针类型是 T (*)[N],它是指向数组的指针,可以直接使用数组下标形式访问元素。释放内存直接使用delete[]。示例代码
#include <iostream>
class A{public:
A()
{
std::cout << "A::A" << std::endl;
}
~A()
{
std::cout << "A::~A" << std::endl;
}
int x;};
int main(){
A (*p)[3] = new A[2][3];
delete[] p;}
执行结果:
A::A
A::A
A::A
A::A
A::A
A::A
A::~A
A::~A
A::~A
A::~A
A::~A
A::~A
可以看到 A 的构造函数和析构函数正常执行。如果觉得 T (*)[N] 繁琐,可以直接使用 auto p = new T[M][N]。三维数组甚至更高维数组都可以使用这种方法。例如,三维数组使用 new T[M][N][O] 进行创建,依旧使用 delete[] p 进行释放。
为什么可以这样写?因为这种多维数组和普通的多维数组都是通过一维数组实现的。例如,int a[6][8],实际上编译器会转化为 int b[6 * 8] 一维数组。然后每次访问二维数组 a[i][j] 相当于访问 b[i * 8 + j]。从二维、三维数组的转化过程中可以发现一些规律。
T a[M][N] --> T b[M * N], a[i][j] --> b[i * N + j]
T a[M][N][O] --> T b[M * N * O], b[i][j][k] --> b[i * N * O + j * O + k]
编译器进行下标转换时,并没有用到第 0 维的大小,而其它维的大小都是必须的。这也就是为什么下面代码能正确执行。
int a[2][3];
int (*p)[3] = a;
由于多维数组本质上是一维数组,所以释放内存都是 delete[] p,而没有奇怪的 delete[][] 语法。

2. 借助指针数组

还有一种方法就是先 new T*[M] 创建一个指针数组,其每个元素保存每一行的首个元素的地址,再使用 new T[N] 创建每一行。示例代码如下:
A** p = new A*[2];
for (int i = 0; i < 2; ++i) {
p[i] = new A[3];
}
for (int i = 0; i < 2; ++i) {
delete[] p[i];
}
delete[] p;
这种方法非常繁琐,首先 new T*[M] 不能写成 new (T(*)[M]),因为它是指针数组而不是数组指针。其次,需要对每一行调用 new T[N]。释放内存时,要先使用 delete[] 释放每一行,再调用 delete[] 释放数组指针。这几个步骤一步都不能错,不然就出现野指针或者内存泄漏。
这种方法唯一的好处就是可以创建交错数组(Jagged Array),也就是每一行的大小不一样。例如:
A **p = new A *[2];
p[0] = new A[3];
p[1] = new A[4];
for (int i = 0; i < 2; ++i){
delete[] p[i];}delete[] p;

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值