C++入门学习4-指针与内存分配,引用
指针与内存
在C++中,一个指针必须在被分配内存之后,才能进行直接赋值的操作,如果没有进行内存的分配,直接对指针进行赋值,是会编译错误的,例如:
int *p=123; //这样是不可取的
我们平时常用的分配内存方式是分配【栈内存】,例如:
int k=123; int *p=&k; *p=345; cout<<k;
因为123被放入了一个变量k中,系统为变量k分配了内存,指针p指向一个有内存空间的地址之后,就可以直接进行赋值了.
动态分配内存:
在系统中除了分配【栈内存】的方式外,还可以分配【堆内存】,分配方式如下:
int *p=NULL; p=new int; //分配堆内存 *p=123; //分配了内存之后,就可以直接进行赋值操作了
函数中的堆内存/栈内存
申请堆内存后,系统不会在程序执行时依据情况自动销毁,若想要释放堆内存空间,必须使用delete关键字;例如,定义两个函数,返回类型都是指针类型,但是一个分配堆内存,一个分配栈内存,在函数结束之后,虽然两个指针都得到了正确的地址,但是被分配 栈内存的指针的内容会被销毁,程序会自行销毁在函数中分配的栈内存,但是不会自行销毁在函数中的堆内存,所以函数执行结束后,要用delete关键字销毁
int *p=NULL; p=newPointer(p); //返回指针类型的函数,并且分配堆内存 delete p; //销毁堆内存
不能对已经销毁的内存赋值 如果一个函数是一个返回指针类型的函数,并且分配栈内存,那么在函数结束后,该指针指向的地址会被摧毁,如果此时仍然对该地址的内容进行赋值操作,更改已经被销毁的内容的数据,会造成一些奇怪的结果,赋值操作不会稳定。可能赋值上了,也可能刚赋值上之后又变成一个随机数
内存丢失 对一个指针申请动态内存之后,如果改变它的指向,那么之前申请的内存就会变得不可用 ,并且无法回收,造成内存泄漏,例如:
int *p=NULL; p=new int; //申请动态内存 *p=123; int k=345; *p=&k; //改变p的指向,那么之前申请的内存就不可用了
内存销毁时,需要保留指向该内存的指针,当没有指针指向一块没被回收的堆内存时,此块内存就如同丢失,成为内存泄漏
如果,接下来的代码不再使用该动态内存,可以选择对其回收
#include<iostream> using namespace std; void swap(int *a,int *b) { int temp=*a; *a=*b; *b=temp; } int main() { int *p=new int; *p=3; int k=5; cout<<p<<" "<<*p<<endl; cout<<&k<<" "<<k<<endl; swap(p,&k); cout<<p<<" "<<*p<<endl; cout<<&k<<" "<<k<<endl; delete p; p=NULL; //先回收动态内存,再将p置空防止调用内存 }
delete p; p=NULL; //先回收动态内存,再将p置空防止调用内存
引用:
引用其实就是相当于给变量一个代称,对代称进行相关的操作等同于对本体进行操作. 左值引用
int &a=x;
右值引用
int &&a=get();
左值引用与右值引用 1.一个引用在被初始化后,无法用它去引用其他的对象. 2.左值引用用来引用变量;而右值引用用来引用临时变量(函数的返回值),并且无法改变. 3.在定义时必须进行初始化.
用引用传递参数/用指针传递参数
引用传参
void swap(int &a,int &b) { int temp=a; a=b; b=temp; } swap(x,y);
指针传参
void swap(int *a,int *b) { int temp=*a; *a=*b; *b=temp; } swap(&x,&y);
main函数
main(int argc,char *argv[])
main函数中的参数可以获取程序运行的命令参数 用数组作为函数的参数,其中: argc可以获取命令参数的个数; argv[]可以获取具体的命令参数(/a /b /c)