自动存储:
函数内部定义的常规变量,被称为自动变量,这意味着他们在所属的函数被调用的时候自动产生,在该函数结束时消亡。
自动变量是一个局部变量,作用域为包含他的代码块,比如int main(){}中定义的int a; 在int abc(){}这个函数中就不能用。
自动变量通常储存在 栈 中,这意味着执行代码块时,其中的变量将依次加入到 栈 中,而离开代码块时,将按相反的顺序释放这些变量,这被称为后进先出(LIFO),因此,在程序执行的过程中,栈将不断的增大和缩小。
静态存储:
静态存储是整个程序执行期间都存在的存储方式。使变量成为静态的方式有两种:
①在函数外面定义他,比如:
#include <iostream> using namespace std; int a = 1; int main() { cout << a; system("pause"); return 0; }
②在声明变量的时候,使用static;如代码:
static int a = 1;
当使用static的时候,能使得函数在调用之后,再次调用的时候,static限定的值能保持在上次调用之后,函数的值。如代码:
#include <iostream> using namespace std; void ab(); int main() { ab(); //调用函数ab ab(); //再次调用函数ab system("pause"); return 0; } void ab() { static int a = 1; //在第一次起作用的时候a=1,后面再次执行的时候不会再次给a赋值为1 cout << "调用ab函数的时候显示a的值:" << a << endl; a = a + 1; cout << "a +1 =" << a << endl;; }
输出:
调用ab函数的时候显示a的值:1 a +1 =2 调用ab函数的时候显示a的值:2 a +1 =3 请按任意键继续. . .
我们发现,第一次执行函数ab()的时候,输出a的值是1,然后在执行函数的时候,a=a+1,于是a=2
当第二次执行函数的时候,a并不是值为1,而是保持了第一次调用函数ab()退出时变量a的值,即a=2。
这是static来限定函数内变量的特点,保持函数变量在退出时的值。
动态存储和内存泄露:
new和delete运算符提供了比静态变量和自动变量更智能的存储方式。
他们管理了一个内存池,这在c++被称为自由存储空间(free store)或堆(heap),该内存池与 用于 静态存储 和 动态存储 的内存是分开的。
使用new在堆 上面创建变量,然后再使用delete进行删除,可以避免内存泄露。如果单纯使用new,而没使用delete,那么将会导致new的内存地址被占用,在整个程序周期之内,就无法再次使用这部分内存了。在极严重的情况下,很可能导致内存被全部用尽,于是程序崩溃。例如代码:
#include<iostream> char *getname(void); using namespace std; int main() { int i; for (i = 1;i<5;i++) { char*a; a = getname(); //这个时候,指针c和指针a的指向内存地址是相同的 cout << "在主函数里,把指针c的地址赋给指针a,指针a的值为" << a << endl; cout << "指针a的地址为" << (int*)a << endl; delete[]a; //删除指针a,因为指针a和指针c指向的内存地址相同,相当于也delete了指针c cout << endl; } system("pause"); return 0; } char*getname() { char*b = new char[20]; //指针b占用了堆中的内存空间 cout << "随便输点什么,别超过20个字符" << endl; cin.get(b, 20).get(); cout << "你输入的是: " << b << endl; cout << "你输入的位置所在的内存地址为:" << (int*)b << endl; char*c = new char[strlen(b) + 1]; //初始化指针c,并位置new一个新的内存地址 strcpy_s(c, strlen(b) + 1, b); cout << "将你输入的字符串复制到指针c的位置。" << endl; cout << "指针c的地址为:" << (int*)c << endl; cout << "指针c所指向地址的值为" << c << endl; delete[]b; //因为指针c和指针a指向相同,在main函数中delete指针a,就相当于delete了指针c。 //但指针b不同,如果不delete指针b,指针b所占用的内存空间就一直存在,于是就可能造成内存泄露 return c; }
因为在getname()函数中,new了2次。在main函数中new了一次,并delete了一次。
首先,main函数中的delete了main函数中new的,
又由于getname()函数中的指针c和main中的指针a相同,于是相当于又delete了一个getname()函数中的指针,但还存在一个指针b没有被删除,这个时候,只有删除了指针b,才可以避免导致内存泄露。