当前位置: 首页 > news >正文

C++:指针(Pointers)

目录

什么是指针?

为什么需要指针?

1. 访问堆(Access Heap)

2. 资源管理(Resource Management) 

3. 参数传递(Parameter Passing)

 如何声明和使用指针?

如何利用指针访问堆内存? 

1. 使用 malloc 访问堆内存 

 2. 使用 new 访问堆内存


什么是指针?

指针是一个地址变量,用于存储数据的地址,而不是数据本身。

普通变量是数据变量,但指针是地址变量,用于间接访问数据。

所以,我们提出问题:为什么我们需要间接访问数据?

为什么需要指针?

1. 访问堆(Access Heap)

程序运行时,RAM(随机存取存储器,Random Access Memory)分为三部分:

  • 代码部分(Code Section):存储程序的机器码(Machine Code),即编译后的指令。

  • 栈(Stack):存储局部变量(Local Variables,如函数内的int、char),由系统自动分配和释放。栈大小有限,变量生命周期随函数作用域结束。

  • 堆(Heap):更大的内存区域,程序员通过动态分配(Dynamic Allocation)使用,生命周期由程序员控制。

程序可以直接访问的部分是代码部分和栈内存,无法直接使用堆内存。所以说,堆内存在程序之外,那么该如何访问堆内存呢?这时就需要用到了指针。 

堆内存的分配需要通过new操作符,分配后返回内存地址,存储在指针中。例如:

int* ptr = new int; // 在堆上分配一个整数,ptr存储其地址
*ptr = 10;         // 通过指针访问堆内存,存储值10

没有指针,程序无法操作堆内存,也就无法实现动态数据结构或存储大块数据。 

2. 资源管理(Resource Management) 

程序运行在内存中,但需要访问外部资源,如文件(Files)、硬盘(Hard Disk)、互联网(Internet)(如网络套接字Socket)。这些资源位于程序外部,操作系统(Operating System)管理它们,程序无法直接访问其内容。

外部资源(如文件、硬盘、互联网连接)由操作系统分配句柄或内存地址,程序通过指针访问这些句柄。例如: 

FILE* fp = fopen("data.txt", "r"); // 打开文件,fp指向文件句柄
if (fp != nullptr) {// 通过fp操作文件fclose(fp); // 关闭文件,释放资源
}

这里,fp是一个指针,指向操作系统分配的文件句柄(File Handle),程序通过它读写文件。

外部资源(如文件、硬盘、互联网)在程序外部,操作系统通过句柄或地址管理,指针是程序访问这些资源的唯一途径。指针通过地址共享资源,提高效率。

 

3. 参数传递(Parameter Passing)

  • C++默认使用值传递(Pass by Value),传递数据副本,函数内修改不影响原数据。复制大对象(如数组、结构体)效率低,且无法修改调用者的变量。

  • 函数需要高效传递数据,有时需要修改原数据,或表示“无数据”状态。

指针支持按地址传递(Pass by Pointer),让函数直接操作调用者的内存。例如:

void swap(int* a, int* b) {int temp = *a; // 访问a的内存*a = *b;       // 修改a的内存*b = temp;     // 修改b的内存
}
int main() {int x = 10, y = 20;swap(&x, &y);  // 传递x和y的地址// x现在是20,y是10
}

 如何声明和使用指针?

这部分不再赘述,详细教程可以参考下面的学习网站: 

C++ 指针 | 菜鸟教程 

如何利用指针访问堆内存? 

1. 使用 malloc 访问堆内存 

malloc(Memory Allocation)是C语言的动态内存分配函数,C++中仍然可用,位于<cstdlib>头文件中。它分配原始内存,不初始化,适合C风格编程。

首先声明一个指针,指定指向的数据类型。

分配堆内存:

ptr = (int*)malloc(sizeof(int)); // 分配一个整数大小的内存
  • 使用malloc分配指定大小的内存,返回void*类型地址,需强制转换为目标类型。

  • 语法:ptr = (type*)malloc(size);

  • sizeof(int):计算整数类型的大小

  • (int*):将void*转换为int*。

访问内存(解引用,Dereference):

  • 通过*操作符访问或修改指针指向的内存。

if (ptr != nullptr) {*ptr = 42; // 存储值42std::cout << *ptr; // 输出:42
}

释放内存:

  • 使用free释放堆内存,防止内存泄漏(Memory Leak)。

free(ptr); // 释放内存
ptr = nullptr; // 避免悬空指针(Dangling Pointer)

 2. 使用 new 访问堆内存

 new是C++的动态内存分配操作符,位于<new>头文件中(通常无需显式包含)。它分配内存并初始化(对于类会调用构造函数),是C++的首选方式。

首先声明一个指针,指定指向的数据类型。

分配堆内存:

  • 使用new分配内存,返回目标类型的指针,无需强制转换。

ptr = new int; // 分配一个整数的内存

访问内存:

  • 通过*操作符访问或修改内存。

*ptr = 100; // 存储值100
std::cout << *ptr; // 输出:100

释放内存:

  • 使用delete释放内存,防止内存泄漏。

delete ptr; // 释放内存
ptr = nullptr; // 避免悬空指针

分配动态数组:

  • 使用new[]分配连续内存,适合动态数组。

int* arr = new int[5]; // 分配5个整数的数组
for (int i = 0; i < 5; i++) {arr[i] = i + 1; // 填充数组:1, 2, 3, 4, 5
}
delete[] arr; // 释放数组内存
arr = nullptr;

关键点

  • new自动匹配指针类型,无需强制转换,比malloc更安全。

  • 对于类,new会调用构造函数,delete调用析构函数,适合面向对象编程。

  • 数组用new[]分配,delete[]释放,匹配使用以避免未定义行为。

http://www.xdnf.cn/news/747757.html

相关文章:

  • 11.3JVM调优
  • 零基础SEO优化操作全解析
  • 2006-2024年 上市公司-企业战略联盟数据-社科经管实证数据
  • 打开NRODIC SDK编译不过怎么处理,keil与segger studio
  • CppCon 2014 学习:Modern Template Metaprogramming A Compendium
  • 【LLM相关知识点】关于LangChain框架学习简单整理(三)
  • C++17新特性 Lambda表达式
  • 神奇的平方和运算
  • 法规解读——GB/T 前向碰撞预警功能FCW
  • kafka学习笔记(三、消费者Consumer使用教程——配置参数大全及性能调优)
  • 数据库核心技术深度剖析:事务、索引、锁与SQL优化实战指南(第三节)----从全局锁到行锁的全面总结
  • ShenNiusModularity项目源码学习(31:ShenNius.Admin.Mvc项目分析-16)
  • 【Doris基础】Apache Doris中的Segment详解:存储与查询的核心组件
  • python分配方案数 2023年信息素养大赛复赛/决赛真题 小学组/初中组 python编程挑战赛 真题详细解析
  • VLAN的作用和原理
  • 命令行式本地与服务器互传文件
  • python:在 PyMOL 中如何查看和使用内置示例文件?
  • MySQL存储架构深度解析:从引擎选型到云原生实践(2025最新版)
  • 【系统配置与部署类】docker的深度配置和应用
  • 5G 网络中的双向认证机制解析
  • 跟单业务和量化交易业务所涉及到的设计模式
  • CP2K 软件介绍与使用指南
  • 34、请求处理-【源码分析】-Model、Map原理
  • MySQL访问控制与账号管理:原理、技术与最佳实践
  • switch-case判断
  • 【PostgreSQL 02】PostgreSQL数据类型革命:JSON、数组与地理信息让你的应用飞起来
  • 若依框架定制化服务搭建
  • 开源是什么?我们为什么要开源?
  • gtsam正确的安装姿势
  • 每日八股文5.31