当前位置: 首页 > 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[]释放,匹配使用以避免未定义行为。

相关文章:

  • 深入理解CSS常规流布局
  • SQL Server 事务详解:概念、特性、隔离级别与实践
  • 关于5090安装tensorrt(python api)的过程
  • reverse_ssh 建立反向 SSH 连接指南 混淆AV [好东西哟]
  • 【鱼皮-用户中心】笔记
  • CppCon 2014 学习:Modern Template Metaprogramming A Compendium
  • OpenLayers 图形交互编辑
  • Leetcode 1908. Nim 游戏 II
  • 数的划分--dfs+剪枝
  • 第3节 Node.js 创建第一个应用
  • vscode不满足先决条件问题的解决——vscode的老版本安装与禁止更新(附安装包)
  • 线程(上)【Linux操作系统】
  • 多类别分类中的宏平均和加权平均
  • Centos系统搭建主备DNS服务
  • pytest中的元类思想与实战应用
  • pytest 中 fixture 与类继承交互导致的问题
  • pytest 常见问题解答 (FAQ)
  • python批量解析提取word内容到excel
  • 【C++高级主题】命令空间(五):类、命名空间和作用域
  • 【Day41】
  • 河南网站平台建设公司/江苏做网站的公司有哪些
  • 成都专业手机网站建设服务/seo排名优化推广报价
  • 上海卫生人才网官网/十大seo公司
  • 建行个人网上银行登录入口官网/seo资料网
  • 做知乎网站社区要多少钱/seo优化上海牛巨微
  • 杂志社网站建设方案书/郑州纯手工seo