5、C++指针(二):指针操作与内存分配

一、原始指针的基本运算

1 - *与&操作

#include <iostream>

using namespace std;
int main()
{
	char ch = 'a';

	// &操作符
	//&ch = 97;                      // &ch左值不合法
	char* cp = &ch;                // &ch右值
	//&cp = 97;                      // &cp左值不合法
	char** cpp = &cp;            // &cp右值

	// *操作符
	*cp = 'a';                           // *cp左值取变量ch位置
	char ch2 = *cp;                 // *cp右值取变量ch存储的值
	//*cp + 1 = 'a';                 //  *cp+1左值不合法的位置
	ch2 = *cp + 1;                  //  *cp+1右值取到的字符做ASCII码+1操作
	*(cp + 1) = 'a';                  //  *(cp+1)左值语法上合法,取ch后面位置
	ch2 = *(cp + 1);                //  *(cp+1)右值语法上合法,取ch后面位置的值

	return 0;
}

2 - ++与- -操作

  • 反汇编查看分析
#include <iostream>

using namespace std;
int main()
{
	char ch = 'a';
	char* cp = &ch;

	char* cp2 = ++cp;
	char* cp3 = cp++;
	char* cp4 = --cp;
	char* cp5 = cp--;
	return 0;
}

在这里插入图片描述

二、C++程序的存储区域划分

1 - 栈和队列

在这里插入图片描述

2 - 代码和数据的存储

在这里插入图片描述

#include <iostream>

int a = 0;						//(GVAR)全局初始化区 
int* p1;						//(bss)全局未初始化区 
int main()						//(text)代码区
{
	int b = 1;					//(stack)栈区变量 
	char s[] = "abc";			//(stack)栈区变量
	int* p2 = NULL;				//(stack)栈区变量
	const char* p3 = "123456";	//123456\0在常量区, p3在(stack)栈区
	static int c = 0;			//(GVAR)全局(静态)初始化区 
	p1 = new int(10);			//(heap)堆区变量
	p2 = new int(20);			//(heap)堆区变量
	char* p4 = new char[7];		//(heap)堆区变量
	strcpy_s(p4, 7, "123456");	//(text)代码区

	//(text)代码区
	if (p1 != NULL)
	{
		delete p1;
		p1 = NULL;
	}
	if (p2 != NULL)
	{
		delete p2;
		p2 = NULL;
	}
	if (p4 != NULL)
	{
		delete[] p4;
		p4 = NULL;
	}
	//(text)代码区
	return 0;					//(text)代码区
}

三、堆heap

  • 动态分配资源 —— 堆heap
    • ①.从现代的编程语言角度来看,使用堆,或者说使用动态内存分配,是一件自然不过的事情
    • ②.动态内存带来了不确定性:内存分配耗时需要多久?失败了怎么办?在实时性要求比较高的场合,如一些嵌入式控制器和电信设备
    • ③.一般而言,当我们在堆上分配内存时,很多语言会使用new这样的关键字,有些语言则是隐式分配
    • ④.在C++中new的对应词是delete,因为C++是可以让程序员完全接管内存的分配释放的
  • 分配和回收动态内存的原则
    • ①.分配一个某个大小的内存块
    • ②.释放一个之前分配的内存块
    • ③.垃圾回收操作,寻找不再使用的内存块并予以释放;这个回收策略需要实现性能、实时性、额外开销等各方面的平衡,很难有统一和高效的做法
  • C++和Java的对比:C++做了①,②两件事;而java则做了①,③两件事

四、资源管理方案 —— RAII

  • RAII的概念:RAII(Resource Acquisition Is Initialization),C++所特有的资源管理方式;有少量其他语言,如D、Ada和Rust也采纳了RAII,但主流的编程语言中,C++是唯一一个依赖RAII来做资源管理的
  • RAII的原理:RAII依托栈和析构函数,来对所有的资源 —— 包括堆内存在内进行管理;对RAII的使用,使得C++不需要类似于Java那样的垃圾收集方法,也能有效地对内存进行管理;RAII的存在,也是垃圾收集虽然理论上可以在C++使用,但从来没有真正流行过的主要原因
  • RAII在C++的使用:RAII有比较成熟的智能指针代表,如std::auto_ptrboost:shared_ptr

五、栈和堆中的变量对比

——栈区(stack)堆区(heap)
作用域函数体内,语句块{}作用域整个程序范围内,由new,malloc开始,delete,free结束
编译间大小确定变量大小范围确定变量大小范围不确定,需要运行期确定
大小范围Windows系统默认栈大小是1M,linux常见默认栈大小是8M或10M所有系统的堆空间上限是接近内存(虚拟内存)的总大小(一部分被OS占用)
内存分配方式地址由高到低减少地址由低到高增加
内容是否可变可变可变

六、全局静态存储区和常量存储区变量对比

——全局静态存储区常量存储区
存储内容全局变量,静态变量常量
编译期间大小是否确定确定确定
内容是否可变可变不可变
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

无休止符

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值