使用new申请空间:
特点:
1、没有名字,只能通过指针间接访问它们。
2、从堆中申请空间
分类:
变量:
语法:指针变量 = new 类型名;
Delete 指针变量
举例:int *p;
p=new int;
delete p;
初始化:
*p=90;
p=new int(99);
一维数组:
语法:指针变量 = new 类型名[下标表达式]; 下标表达式是整型常量或整型表达式
Delete [ ]指针变量;---[ ]表明是个数组,但不需要指出其大小
举例:Int *p;
P= new type[s];
Delete [ ]p;
多维数组(二维数组): 必须指出所有维的长度
语法:指针变量 = new 类型名[下标表达式] [下标表达式];
Delete [ ]变量名
举例:定义一个3×4的数组
Int (*p)[4]; p是个指针,它指向一个n维数组(4定义的时候必须已知,即后几维必须已知)
p=new int[3][4];// 第一维可以是常量或表达式,其他维必须全部为常量
Delete [ ]p;
对象:可以在创建对象的时候同时进行初始化
语法: 类名 *指针变量 = new 类名(实参表);
对象数组:
语法:类名 数组名[元素个数];
或: 类名* 指针名;指针名=new 类名[数组长度];
举例:Point A[2];
Point* p;
*p=new Point[5];
delete [ ]p;
初始化:每个对象都要调用一次构造函数和一次析构函数。
1)对象数组确定且长度有限:可以使用参数列表初始化
Point A[2]={Point(1,2),Point(3,4)};
2)对象数组长度比较大或不确定:只能调用无参或者使用缺省参数的函数
Point A[2];
原因:在建立对象数组的时候,C++不允许整体对对象进行初始化(即[ ]和( )不能一起使用),这时不能给对象 使用有参数的构造函数
所以:若创建一个类的对象数组,就对给类的构造函数有要求:对象数组只能调用一个不需要参数的构造函数
常见问题:
1):有了malloc/free 为什么还要new/delete?
malloc/free 只能满足内部数据类型的变量,它们只需要申请空间,无法对空间进行操作
而对于非内部数据类型的对象来说,对象在创建的同时要自动执行构造函数,在消亡之前要自动执行析构函数。
由于malloc/free 是库函数而不是运算符,不在编译器控制权限之内,不能够自动地调用构造函数和析构函数。即用无法满足动态对象的要求。
因此 C++语言需要一个能完成动态内存分配和初始化工作的运算符new,以及一个能完成清理与释放内存工作的运算符delete。
注意new/delete 不是库函数,而是运算符。malloc/free 是标准库函数。
2):malloc/free 和 new/delete 的相同点和不同点
相同点:它们都可以申请和释放空间。
不同点:
一、new :分配内存 + 调用类的构造函数 + 初始化 delete:释放内存 + 调用类的析构函数
malloc:只分配内存,不会进行初始化类成员的工作 free只释放内存,不会调用析构函数
二、new delete 是运算符,可以进行重载
malloc,free是函数,不可以进行重载
三、new delete 更加安全,简单:
不用计算类型大小:自动计算要分配存储区的字节数
不用强制类型转换:自动返回正确的指针类型
四、new可以分配一个对象或对象数组的存储空间,malloc不可以
五、可以超载与类相关的new和delete
六、malloc/free 是标准库函数,new/delete是C++运算符
2):new和delete搭配使用,malloc和free搭配使用:混搭可能出现不可预料的错误
3):new后执行的三个操作:(某面试题目)
1、new的类分配内存空间。
2、 调用类的构造方法。
3 、返回该实例(对象)的内存地址
一.malloc
原型:extern void *malloc(unsigned int num_bytes);
使用格式(类型)malloc(长度) (char*)malloc(x*sizeof(char)) (int*)malloc(y*sizeof(int)) x,y代表实际分配的个数
头文件:#include <malloc.h>
功能:分配长度为num_bytes字节的内存块
说明:如果分配成功则返回指向被分配内存的指针,否则返回空指针NULL。当内存不再使用时,应使用free()函数将内存块释放。
二:new运算符
new是 c++ 的一个关键字。被当作像 + 、 - 、 * 、 / 一样的操作符 。
• new 的作用 申请到指定数据类型大小的内存空间。
• new 的返回值 是申请到的内容空间的地址。
• new 的语法: new 数据类型
• 实际使用方法: 数据类型 指针变量 = new 数据类型 ;
new 将做三件事:
( 1 )主动计算指定数据类型需要的内存空间大小;
( 2 )返回正确的指针类型;
( 3 )在分配内存时,按照语法规则,初始化所分配的内存。
注意:用 new 分配数组空间时不能指定初值。
例:
• int * p ; // 声明了一个 p 指针,放在栈里面的
• p = new int(100); // 用 new 开辟的整型数据空间放在堆里面,此空间存储 100 ,指针 p 指向这块动态开辟的空间。
• *p=10 ; // 将 p 指针所指向的空间内容变为 10
• delete p ; // 把 p 指向内存释放掉
• 注意 :释放的动态开辟的空间,而指针 p 还是存在的,还在栈里面。
malloc与new的不同点
从函数声明上可以看出。malloc 和 new 至少有两个不同: new 返回指定类型的指针,并且可以自动计算所需要大小。比如:
int *p;
p = new int; //返回类型为int* 类型(整数型指针),分配大小为 sizeof(int);
或:
int* pa;
pa = new int [100]; //返回类型为 int* 类型(整数型指针),分配大小为 sizeof(int) * 100;
而 malloc 则必须由我们计算要字节数,并且在返回后强行转换为实际类型的指针。
int* p;
p = (int *) malloc (sizeof(int));
第一、malloc 函数返回的是 void * 类型,如果你写成:p = malloc (sizeof(int)); 则程序无法通过编译,报错:“不能将 void* 赋值给 int * 类型变量”。所以必须通过 (int *) 来将强制转换。
第二、函数的实参为 sizeof(int) ,用于指明一个整型数据需要的大小。如果你写成:
int* p = (int *) malloc (2);
代码也能通过编译,但事实上只分配了2个字节大小的内存空间,当你往里头存入一个整数,就会有2个字节无家可归,而直接“住进邻居家”!造成的结果是后面的内存中原有数据内容全部被清空。
malloc 也可以达到 new [] 的效果,申请出一段连续的内存,方法无非是指定你所需要内存大小。
比如想分配100个int类型的空间:
int* p = (int *) malloc ( sizeof(int) * 100 ); //分配可以放得下100个整数的内存空间。
另外有一点不能直接看出的区别是,malloc 只管分配内存,并不能对所得的内存进行初始化,所以得到的一片新内存中,其值将是随机的。
除了分配及最后释放的方法不一样以外,通过malloc或new得到指针,在其它操作上保持一致。
int **a = new int* [m] //分配一个指针数组,将其首地址保存在a中 、
for(int i = 0; i < m; i++) //为指针数组的每个元素分配一个数组
a[i] = new int [n];
相当于产生了一个二维数组 a[m][n]了
静态声明的数组可以有公式(假设也是m行n列)
b[i][j] = b[i*n +j]
这是因为数组b是连续的一片内存,而动态声明的数组任意的a[k]都是一个int*类型,即一个地址,所以只能a[i][j]或者*(*(a+i) + j)来访问数组的元素,而不能a[i*n + j]使用。
动态声明的数组,使用后需要释放内存。
for(int i = 0; i < m; ++i)
delete []a[i];
delete []a;
#include <iostream>
#include <vector>
using namespace std;
/*
C++建立动态二维数组主要有两种方法:
1.使用数组指针,分配一个指针数组,将其首地址保存在b中,然后再为指针数组的每个元素分配一个数组
2.利用vector
*/
int main01()
{
int row = 10;
int col = 10;
//创建行指针
int **b = new int*[row];//分配一个指针数组,将其首地址保存在b中
//为每一行分配空间
for (int i = 0; i < row; i++) //为指针数组的每个元素分配一个数组
{
b[i] = new int[col];
}
//使用
//使用空间
//给二维数组赋值
for (int j = 0; j < row; j++)
for (int k = 0; k < col; k++)
b[j][k] = rand() % 100;
//打印二维数组
for (int j = 0; j < row; j++)
{
cout << endl;
for (int k = 0; k < col; k++)
{
b[j][k] = rand() % 100;
cout << b[j][k] << " ";
}
}
//删除二维数组
//该方法定义的动态二维数组的释放需先释放指针数组的每个元素指向的数组,然后再释放该指针数组:
for (int i = 0; i < row; i++)//删除行数组空间
{
delete[] b[i];
b[i] = NULL;
}
delete[] b;//删除行指针
b = NULL;
system("pause");
return 0;
}
int main()
{
int row, column;
cin >> row >> column;
//申请空间
vector< vector<int> > a(row,vector<int>(column));
//使用空间
for (int j = 0; j < row; j++)
for (int k = 0; k< column; k++)
a[j][k] = rand() % 100;
for (int j = 0; j < row; j++)
{
cout << endl;
for (int k = 0; k< column; k++)
{
a[j][k] = rand() % 100;
cout << a[j][k] << " ";
}
}
system("pause");
return 0;
}