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

目录

  • 一、原始指针的基本运算
    • 1 - *与&操作
    • 2 - ++与- -操作
  • 二、C++程序的存储区域划分
    • 1 - 栈和队列
    • 2 - 代码和数据的存储
  • 三、堆heap
  • 四、资源管理方案 —— RAII
  • 五、栈和堆中的变量对比
  • 六、全局静态存储区和常量存储区变量对比

一、原始指针的基本运算

1 - *与&操作

#include 

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 

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;
}

5、C++指针(二):指针操作与内存分配_第1张图片

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

1 - 栈和队列

5、C++指针(二):指针操作与内存分配_第2张图片

2 - 代码和数据的存储

5、C++指针(二):指针操作与内存分配_第3张图片

#include 

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占用)
内存分配方式 地址由高到低减少 地址由低到高增加
内容是否可变 可变 可变

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

—— 全局静态存储区 常量存储区
存储内容 全局变量,静态变量 常量
编译期间大小是否确定 确定 确定
内容是否可变 可变 不可变

你可能感兴趣的:(C++知识体系重构,c++,c语言,visual,studio)