第二章 基本语言
第四节 范围for、new内存动态分配、nullptr
1. 范围for语句
- 用于遍历一个序列
#include<iostream>using namespace std;intmain(){intv[]{12,13,15,17,88};// 数组v中每个元素,依次放入x中并打印x的值,把v中每个元素的值拷贝到x中,打印x的值for(autox:v){cout<<" x: "<<x;}cout<<endl;// 存在拷贝操作for(autox:{'F','E','L','A','I','M'}){cout<<x;}cout<<endl;// 改成引用,减少拷贝操作for(auto&x:v){cout<<" x: "<<x;}cout<<endl;return0;}2. 动态内存分配问题
c语言中:供程序使用的存储空间,有程序区,静态存储区,动态存储区
c++中,我们将内存详细分为五个区:
栈: 一般函数内的局部变量都会放在栈里,由编译器自动分配和释放
堆: 程序员malloc/new分配,用free/delete来释放,忘记释放后,系统会回收
全局/静态存储区: 放静态变量(static)和全局变量,程序结束后系统释放
常量存储区: “I am Felaim”
程序代码区
- 堆和栈不同的用处和区别:
栈: 空间是有限的,系统规定的,分配速度快
堆: 只要不超出实际拥有的物理内存,在操作系统允许能够分配的最大内存大小之内,都可以进行分配,
分配速度比栈慢,可以随时new/malloc来分配,free/delete来释放内存,非常灵活
- malloc和free: 在c语言中使用malloc和free从堆中分配和释放内存使用
malloc(memory allocation): 动态内存分配
一般形式: void *malloc(int NumBytes); //NumBytes: 要分配的字节数,
如果分配成功则返回指向被指向分配内存的指针,分配失败则返回NULL.这段分配的内存不使用时,
使用free()函数来将内存释放掉,供其他地方使用free: void free(void* FirstBytes);将之前用malloc分配的内存还给程序(操作系统)
- 实例一
#include<iostream>using namespace std;intmain(){int*p=NULL;//等价于数字0//在堆中分配4个字节p=(int*)malloc(sizeof(int));if(p!=NULL){//分配成功*p=5;cout<<*p<<endl;// 释放指针free(p);}return0;}- 实例二
#include<iostream>#include<cstring>using namespace std;intmain(){char*point=NULL;point=(char*)malloc(100*sizeof(char));//100个if(point!=NULL){//如果malloc少于string的长度,也会copy成功,不是很安全strcpy(point,"I am Felaim!");cout<<point<<endl;free(point);}return0;}- 实例三
#include<iostream>#include<cstring>using namespace std;intmain(){int*p=(int*)malloc(100*sizeof(int));if(p!=NULL){int*q=p;*q++=1;//==>*(q++): *q =1; q++*q++=5;cout<<*p<<endl;cout<<*(p+1)<<endl;free(p);}return0;}- new和delete: 在c++中使用new和delete从堆中分配和释放内存使用
是运算符(标识符),在c++中就使用new和delete分配和释放内存,不在使用malloc/free来分配内存
new/delete和malloc/free一样,分配和释放内存,new/delete的功能性更强(调用构造函数等)
- new一般使用的格式:
指针变量名 = new 类型标识符;
指针变量名 = new 类型标识符(初始值) //()括起来,表示初始值
指针变量名 = new 类型标识符[内存单元个数] // 注意,这里是[]
- 范例一
#include<iostream>#include<cstring>using namespace std;intmain(){int*myint=newint;if(myint!=NULL){// *myint 代表指针的变量*myint=8;cout<<*myint<<endl;delete(myint);}return0;}- 范例二
#include<iostream>using namespace std;intmain(){int*myint=newint(18);if(myint!=NULL){// *myint 代表指针的变量cout<<*myint<<endl;delete(myint);}return0;}- 范例三
#include<iostream>using namespace std;intmain(){// 开辟大小为100个整型数组int*myint=newint[100];if(myint!=NULL){// *myint 代表指针的变量int*q=myint;*q++=1;*q++=88;cout<<*myint<<endl;cout<<*(myint+1)<<endl;// 释放int myint数组空间// new的时候使用[],delete就必须使用[],中括号中不用写大小delete[]myint;}return0;}额外强调
配对使用,有malloc成功必然有free, 有new成功必然有detete
free/delete,不要重复调用
malloc/free和new/free的区别, new多做了初始化,delete中调用了析构函数等
3. nullptr
c++11中引入了新关键字,代表的也是空指针
所以在编译的时候如果报一堆nullptr的问题,就需要添加c++11的支持
使用nullptr能够避免整数和指针之间的混淆
NULL和nullptr实际上是不同的类型
对于指针初始化,能用nullptr就是用nullptr进行取代
#include<iostream>#include<typeinfo>using namespace std;intmain(){char*p=NULL;char*q=nullptr;if(p==nullptr){cout<<"good!"<<endl;}if(q==NULL){cout<<"good!"<<endl;}cout<<"NULL: "<<typeid(NULL).name()<<endl;cout<<"nullptr: "<<typeid(nullptr).name()<<endl;// //可行相当于赋值0// int a = NULL;// //不可行报错// int b = nullptr;return0;}