栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C++知识点详细分析--02篇(适合有基础的C语言,重点(C++灵魂):引用)

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C++知识点详细分析--02篇(适合有基础的C语言,重点(C++灵魂):引用)

十一、内存分区模型。

1、在C++程序执行时,将内存大方向可以划分为4个区域。
1)代码区:存放函数的二进制代码,由操作系统进行管理。
2)全局区:存放全局变量、静态变量以及常量。
3)堆区:由工程师分配和释放、若不释放,程序结束时由操作系统回收。
4)栈区:由编译器自动分配释放、存放着函数参数值,局部变量等。

2、内存四区意义?
不同区域存放不同的数据,赋予不同的生命周期,给我们更大的灵活编程。

十二、程序运行前。

在程序编译后,生成一个可执行程序,未执行该程序前分为两个区域:
1、代码区:
存放CPU执行的机器指令。 -> 其实指的就是0101这种数据。

代码区是共享的,共享的目的是对于频繁被执行的代码,只需要在内存中有一份代码即可。
无论执行了多少次程序,都是使用同一个代码。

代码区是只读的,使其只读的原因是防止程序意外地修改它的指令。

2、全局区:
全局变量与静态变量存放在此。
全局区还包含了常量区、字符串常量、其他常量(const修饰的变量)在存放在此。
该区域的数据在程序结束之后由操作系统来释放

#include 
using namespace std;

//2. 创建全局变量
int g_a = 10;
int g_b = 20;     //全局变量: 全局区

//5. const修饰全局变量  -> 全局常量
const int c_g_a = 10;
const int c_g_b = 10;

int main(int argc,char *argv[])
{
	//1. 创建局部变量
	int a = 10;
	int b = 20;

	cout << "&a = " << &a << endl;
	cout << "&b = " << &b << endl;   //局部变量:栈区

	cout << "&g_a = " << &g_a << endl;
	cout << "&g_b = " << &g_b << endl;

	//3. 静态变量
	static int s_a = 10;
	static int s_b = 20;

	cout << "&s_a = " << &s_a << endl;
	cout << "&s_b = " << &s_b << endl;   //静态变量: 全局区

	//4. 常量区
	//字符串常量
	cout << "string addr = " << &"helloworld" << endl;   //字符串常量: 全局区

	//const修饰的变量
	//const修饰全局变量、const修饰局部变量。
	cout << "&c_g_a = " << &c_g_a << endl;
	cout << "&c_g_b = " << &c_g_b << endl;

	const int c_l_a = 10;  //局部常量
	const int c_l_b = 20; 

	cout << "&c_l_a = " << &c_l_a << endl;
	cout << "&c_l_b = " << &c_l_b << endl;   //局部常量:栈区

	return 0;
}

运行结果:

wzf@ubuntu:/mnt/hgfs/C++$ ./all
&a = 0x7ffd6293a768
&b = 0x7ffd6293a76c
&g_a = 0x602070
&g_b = 0x602074
&s_a = 0x602078
&s_b = 0x60207c
string addr = 0x400c57
&c_g_a = 0x400c14
&c_g_b = 0x400c18
&c_l_a = 0x7ffd6293a770
&c_l_b = 0x7ffd6293a774

结论:
1.不在全局区:
局部变量 0x7ffd6293a768
const修饰的局部变量(局部常量) 0x7ffd6293a770

2.在全局区:
全局变量 0x602070
静态变量 使用static修饰 0x602078

常量
字符串常量 0x400c57
使用const修饰的全局变量(全局常量) 0x400c14

十三、程序运行后。

栈区: 由编译器自动分配释放,存放函数的参数值,局部变量等。
注意: 不要返回局部变量的地址,栈区开辟的数据由编译器自动释放。

#include 
using namespace std;

//栈区:存放函数的参数值,局部变量
//不要返回局部变量的地址
int *fun(int b)  //b是形式参数,是存放在栈区
{
	int a = 10;  //a是局部变量,是存放在栈区    -> 开始申请a的空间
	return &a;  //因为返回时,局部变量的空间会释放掉。
						   -> 开始释放a的空间
}

int main(int argc,char *argv[])
{
	int *p = fun(1);   //返回到主函数时,a的空间已经释放掉了。
	cout << "p = " << p << endl;   //0 -> NULL
	cout << "*p = " << *p << endl; // *NULL 就是段错误

	return 0;
}

结果:

wzf@ubuntu:/mnt/hgfs/C++$ ./stack
p = 0    -> 正常来讲,应该返回a的地址,但是由于a的空间释放掉,为了防止用户去访问该区域,所以返回安全指针NULL给函数调用的地方。
Segmentation fault (core dumped)

堆区: 由工程师分配和释放,若不释放,程序结束时由操作系统来回收。
在C++中主要利用new在堆区开辟空间。

#include 
using namespace std;

int *func()
{
	//利用new关键词,可以将数据开辟到堆区
	int *a = new int(10);
	return a;  //函数返回时,堆空间不会释放。
}

int main(int argc,char *argv[])
{
	int *p = func();
	cout << "p = " << p << endl;
	cout << "*p = " << *p << endl;

	return 0;
}

结果:

wzf@ubuntu:/mnt/hgfs/C++$  ./heap
p = 0xd19c20
*p = 10
十四、new操作符。

C++中利用new操作符在堆区开辟数据。
堆区中开辟的数据,由工程师手动开辟,手动释放,释放利用操作符delete
语法: new 数据类型
利用new创建的数据,会返回该数据对应的类型的指针。

1、堆区的基本语法示例。

#include 
using namespace std;

//语法: new 数据类型
//返回该数据类型对应的类型的指针

int *func()
{
	//在堆区创建整型数据
	int *p = new int(10);
	return p;
}

int main(int argc,char *argv[])
{
	int *p = func();
	cout << "*p = " << *p << endl;  //10

	//堆区的数据由用户自己来释放。
	delete p; 
	p = NULL; 
	
	cout << "*p = " << *p << endl;  //0 

	return 0;
}

2、在堆区利用new开辟数组。

#include 
using namespace std;

int main(int argc,char *argv[])
{
	//创建10个整型的数据在堆区。
	int *arr = new int[10];  //10代表数组有10个元素

	int i;
	for(i=0;i<10;i++)
	{
		arr[i] = i + 100;  //给10个元素赋值  100~109
	}

	for(i=0;i<10;i++)
	{
		cout << arr[i] << endl;
	}

	//释放数组时,需要加[]才可以。
	delete[] arr;

	return 0;
}
十五、引用的基本使用。

1、引用作用:
给变量起别名。

2、语法。
数据类型 &别名 = 原名

#include 
using namespace std;

//引用作用:给变量起别名
//引用语法: 数据类型 &别名 = 原名

int main(int argc,char *argv[])
{
	int a = 10;

	//创建引用
	int &b = a;

	cout << "a = " << a << endl; //10
	cout << "b = " << b << endl; //10

	b = 100;

	cout << "a = " << a << endl; //100
	cout << "b = " << b << endl; //100

	return 0;
}
十六、引用注意事项。

1、引用必须初始化。
2、引用在初始化后,不可以改变。

#include 
using namespace std;

int main(int argc,char *argv[])
{
	//1、引用必须初始化。
	//int &c;   //编译出错,引用必须初始化,必须要引用一块合法并且存在的空间。

	//2、引用在初始化后,不可以改变。
	int a = 10;
	int b = 20;

	//创建引用
	int &c = a;   //一旦初始化了,就不可以更改。(c永远都是a的别名)

	c = b;  //这是赋值操作
		//不是让c去做b的别名
	cout << "a = " << a << endl;  //20
	cout << "b = " << b << endl;  //20
	cout << "c = " << c << endl;  //20

	return 0;
}
十七、引用做函数参数。

作用:函数传参时,可以利用引用的技术让形参修饰实参。
优点:可以简化指针修饰实参的方法。

#include 
using namespace std;

//1. 值传递
void mySwap01(int a,int b)  //a = 10  b = 20
{
	int temp = a;
	a = b;
	b = temp;
}

//2. 地址传递
void mySwap02(int *a,int *b)
{
	int temp = *a;
	*a = *b;
	*b = temp;
}

//3. 引用传递
void mySwap03(int &a,int &b)  //int &a = a   int &b = b   //修改形参a,就等于修改实参a
{
	int temp = a;
	a = b;
	b = temp;
}

int main(int argc,char *argv[])
{
	int a = 10;
	int b = 20;

	//mySwap01(a,b);
	//mySwap02(&a,&b);
	mySwap03(a,b);

	cout << "a = " << a << endl;
	cout << "b = " << b << endl;

	return 0;
}
十八、引用做函数返回值。

作用:引用是可以作为函数返回值存在的。

注意事项:
1、不要返回局部变量的引用。
2、函数调用作为左值的存在。

#include 
using namespace std;



//int -> 返回的是10(本体的值)
//int test01()

//int&  -> 返回的是a(本体)
int &test01()
{
	//1、不要返回局部变量的引用。
	//int a = 10; //局部变量
	static int a = 10;
	return a;
}

int main(int argc,char *argv[])
{
	int &ret = test01();
	cout << "ret = " << ret << endl;  //10

	//2、函数调用作为左值的存在。
	//test01(); // -> 返回是a的本体

	//test01() = 1000;
	//cout << "ret = " << ret << endl; //1000

	return 0;
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/330206.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号