一、内存分为四个区:代码区、全局区、栈区、堆区。
二、程序运行前只有:代码区和全局区。
1、代码区:共享和只读
2、全局区
(1)、保存在全局区中的变量为:全局变量、静态变量、const修饰的全局变量、字符串常量
- 当将一个局部变量定义成 static 时,该局部变量将会存在于整个程序的生命周期中,即使该变量所在的函数执行结束也不会对其造成影响。
#include<iostream>
#include<string>
using namespace std;
int g_a; //全局变量(在函数体外部)——放在全局区
const int C_a = 10; //全局常量(const修饰的全局常量)——放在全局区
int main()
{
// 全局区包含:全局变量、静态变量、常量
static int s_a = 10; //静态变量——放在全局区
cout << "g_a的地址为: " << (int)&g_a << endl;
cout << "C_a的地址: " << (int)&C_a << endl;
cout << "s_a的地址: " << (int)&s_a << endl;
cout << "字符串常量地址: " << (int)&"Hello" << endl;
cin.get();
}
(2)、不在全局区中的变量:局部变量、const修饰的局部变量
#include<iostream>
#include<string>
using namespace std;
int main()
{
string str1 = "Hello"; //局部变量(字符串)
const int C_b = 20; // 局部常量(const修饰的局部常量),不在全局区
int L_a; //函数体内部的为局部变量
cout << "str1的地址: " << (int)&str1 << endl;
cout << "C_b的地址: " << (int)&C_b << endl;
cout << "L_a的地址为: " << (int)&L_a << endl;
cin.get();
}
三、程序运行后
1、栈区:由编译器自动分配释放,存放函数的形参值、局部变量等
【注意】:不要返回局部变量的地址,因为局部变量是保存在栈区上的,栈区的数据在函数执行完后会自动释放。栈区会由编译器自动释放,从而会得到清空后的地址,而引发错误。(但是可以返回局部变量的值)
返回局部变量地址时,出现错误的实例如下:
#include<iostream>
#include<string>
using namespace std;
int* func()
{
int a = 10; // 局部变量存放在栈区,栈区上的数据在函数执行完会自动释放
return &a; // 返回局部变量的地址
}
int main()
{
int *p = func(); // 定义指针变量来接受函数的返回值
cout << *p << endl; //第一次可以正确输出数字,因为编译器做了保留
cout << *p << endl; // 第二次这个数据就不再保存了,这块地址上的内容已经被释放了
cin.get();
}
2、堆区:堆区由程序员分配释放,若程序员不释放,则程序结束后由操作系统回收。
(1)、在C++ 中主要使用 new 关键字在堆区中开辟内存。
【注意】:new 返回的是该数据类型的指针,所以需要用指针来接受其返回的地址。如 int * p = new int(10)
#include<iostream>
#include<string>
using namespace std;
int* func()
{
// 利用new关键字可以在堆区开辟内存。
int *p = new int(10); // new 关键字将开辟的内存地址编号返回,可以用指针来接受该地址
return p;
}
int main()
{
int *p = func(); // 定义指针变量来接受函数的返回值
// 该数据由程序员释放,若不主动释放,在程序运行中会一直存在。
cout << *p << endl;
cout << *p << endl;
cin.get();
}
(2)、new 的用法
#include<iostream>
#include<string>
using namespace std;
int* func()
{
// 利用new关键字可以在堆区开辟内存。
int *p = new int(10); // 创建一个变量,new 返回的是该数据类型的指针
return p;
}
void test01()
{
int *p = func();
// 该数据是在堆区中,由程序员来开辟和释放。
cout << *p << endl;
cout << *p << endl;
cout << *p << endl;
// 释放new所开辟的内存空间
delete p; //释放之后将不能再来操作该空间中的内容
}
// 在堆区利用new 开辟数组
void test02()
{
int *arr = new int[10]; //new 开辟一个含有10个元素的数组,并返回该数组的首地址。
for (int i = 0; i < 10; i++)
{
arr[i] = i + 100;
}
for (int i = 0; i < 10; i++)
{
cout << arr[i] << endl;
}
// 释放在堆区所开辟的该数组空间
delete[] arr; // 释放数组时前面要加[]
}
int main()
{
test01();
test02();
cin.get();
}