文章目录
- 第一章:
- 1.内存分区模型
- 1.1 程序运行前
- 1.2 程序运行后
- 1.3 new操作符
- 第二章:
- 2.引用
- 2.1 使用
- 2.2 注意事项
- 2.3 做函数参数
- 2.4 做函数返回值
- 2.5 本质
- 2.6 常量引用
第一章:
1.内存分区模型
4个区域:
-
代码区:存放函数的二进制代码,由操作系统进行管理。
-
全局区:存放全局变量和静态变量以及常量。
-
栈区:由编译器自动分配释放,存放函数参数值,局部变量等。
-
堆区:由程序员分配和释放,程序员不释放的话,将由程序结束时操作系统回收。
意义:不同区域存放的数据,赋予不同生命周期,给程序员更大的空间去进行编程。
1.1 程序运行前
两个区域:
-
代码区:
存放CPU执行的机器指令。
代码区是共享的,目的是为了对频繁被执行的程序,在内存中只需有一份代码即可。
代码区是只读的,目的是为了防止程序被意外修改了它的指令。
-
全局区:
全局变量和静态变量,还包含了常量区,字符串常量和其他常量也存放在全局区。
全局区的数据在程序结束后由操作系统进行释放。
#include <iostream>
using namespace std;
//全局变量
int g_a = 1;
int g_b = 1;
//const修饰全局常量
const int c_g_a = 1;
const int c_g_b = 1;
int main()
{
//c - const g - global l - local
//局部变量
int a = 1;
int b = 1;
//静态变量
static int s_a = 1;
static int s_b = 1;
//局部常量
const int c_l_a = 1;
const int c_l_b = 1;
cout << "局部变量a的地址为:" << &a << endl;
cout << "局部变量b的地址为:" << &a << endl;
cout << "全局变量g_a的地址为" << &g_a << endl;
cout << "全局变量g_b的地址为" << &g_b << endl;
cout << "静态变量s_a的地址为:" << &s_a << endl;
cout << "静态变量s_b的地址为:" << &s_b << endl;
cout << "字符串常量的地址为:" << &"Hello" << endl;
cout << "const修饰的全局常量c_g_a的地址为:" << &c_g_a << endl;
cout << "const修饰的全局常量c_g_a的地址为:" << &c_g_b << endl;
cout << "局部常量c_l_a的地址为:" << &c_l_a << endl;
cout << "局部常量c_l_b的地址为:" << &c_l_b << endl;
system("pause");
return 0;
}
1.2 程序运行后
-
栈区:
由编译器自动分配释放,存放函数参数值,局部变量等。
不要返回局部变量的地址,因为栈区开辟的数据由编译器自动释放掉。
#include <iostream>
using namespace std;
int* fun(int b)
{
b = 2;
int a = 1;
return &a;
}
int main()
{
int* p = fun(10);
cout << "fun函数返回的值为:" << *p << endl; //第一次打印正确的数字1,因为编译器做了保留。
cout << "fun函数返回的值为:" << *p << endl; //第二次打印随机数
system("pause");
return 0;
}
-
堆区:
由程序员分配释放,如果程序员不释放,程序结束时由操作系统进行回收。
使用new在堆区进行开辟内存空间。
#include <iostream>
using namespace std;
int* fun()
{
int *p = new int(1); //指针也是局部变量,存放在栈区,但指针保存的数据存放在堆区
return p;
}
int main()
{
int* p = fun();
cout << "指针p指向的内容为:" << *p << endl;
cout << "指针p指向的内容为:" << *p << endl;
cout << "指针p指向的内容为:" << *p << endl;
system("pause");
return 0;
}
1.3 new操作符
作用:在堆区开辟数据。
语法结构:
-
开辟:new 数据类型
-
释放:delete 数据类型
使用new创建的数据,会返回该数据对于的类型指针。在堆区开辟的空间,需要程序员手动释放,释放使用操作符delete。
#include <iostream>
using namespace std;
int* fun()
{
int *p = new int(1);
return p;
}
void fun2()
{
//在堆区开辟10个整型数据的数组
int* arr = new int[10];
for (int i = 0; i < 10; i++)
{
arr[i] = i;
}
for (int i = 0; i < 10; i++)
{
cout << arr[i] << " ";
}
cout << endl;
delete[] arr;
}
int main()
{
int* p = fun();
fun2();
cout << *p << endl;
cout << *p << endl;
cout << *p << endl;
delete p;
return 0;
}
第二章:
2.引用
2.1 使用
作用:给变量起别名。
语法结构:数据类型 &别名 = 原名
#include <iostream>
using namespace std;
int main()
{
int a = 10;
int& b = a;
cout << "a = " << a << endl;
cout << "b = " << b << endl;
b = 20;
cout << "a = " << a << endl;
cout << "b = " << b << endl;
system("pause");
return 0;
}
2.2 注意事项
-
引用必须初始化
-
在初始化后不可修改
#include <iostream>
using namespace std;
int main()
{
int x = 10;
int y = 20;
//int& z; //报错
int& z = x;
z = y; //此处是赋值操作,而不是更改引用!
cout << "x = " << x << endl; //20
cout << "y = " << y << endl; //20
cout << "z = " << z << endl; //20
system("pause");
return 0;
}
2.3 做函数参数
作用:函数传参的时候,使用引用的技术让形参修饰实参。可简化指针修改实参。
#include <iostream>
using namespace std;
void swap(int &a , int &b)
{
int temp = a;
a = b;
b = temp;
}
int main()
{
int a = 10;
int b = 20;
swap(a, b);
cout << "a = " << a << endl; //20
cout << "b = " << b << endl; //10
system("pause");
return 0;
}
2.4 做函数返回值
作用:作为函数返回值所存在。
#include <iostream>
using namespace std;
int& test1()
{
int a = 10;
return a;
}
int& test2()
{
static int a = 10;
return a;
}
int main()
{
int& ret1 = test1();
cout << "ret1 = " << ret1 << endl;
cout << "ret1 = " << ret1 << endl;
int& ret2 = test2();
cout << "ret2 = " << ret2 << endl;
cout << "ret2 = " << ret2 << endl;
test2() = 20;
cout << "ret2 = " << ret2 << endl;
cout << "ret2 = " << ret2 << endl;
system("pause");
return 0;
}
补充:不要返回局部变量引用。
2.5 本质
在C++内部实现是一个指针常量。
#include <iostream>
using namespace std;
void fun(int& ret) //转换为:int* const ret = &a;
{
ret = 30; //转换为:*ret = 30;
}
int main()
{
int a = 10;
int& ret = a; //自动转换为:int* const ret = &a;指针常量的指针指向不可改
ret = 20;
cout << "a = " << a << endl;
cout << "ret = " << ret << endl;
fun(a);
system("pause");
return 0;
}
2.6 常量引用
作用:修饰形参,防止误操作。
函数形参列表中,可加const修饰形参,以便防止形参改变实参。
#include <iostream>
using namespace std;
void Show1(int& x)
{
x = 20;
cout << x << endl; //20
}
void Show2(const int& x)
{
x = 20; //报错
cout << x << endl;
}
int main()
{
//int& ref = 10; //报错,引用本身需一个合法的内存空间
//const int& ref = 10; //加入const,编译器会将代码修改成 int temp = 10;const int& ref = temp;
//ref = 20; //报错,加了const变得只读,不可修改
int a = 10;
Show1(a);
cout << a << endl; //20
system("pause");
return 0;
}