指针和引用
在 C++ 中,指针和引用是允许直接内存操作和高效数据传递的基本概念。它们对于理解 C++ 如何管理内存以及与硬件交互至关重要,并且它们与 JavaScript 的内存模型有显著差异。
指针概念和语法
指针是一个存储另一个变量内存地址的变量。它“指向”内存中存储值的位置。指针功能强大,但需要仔细处理。
声明和初始化指针
int* ptr;
// 声明一个指向整数的指针。int* ptr = &variable;
// 使用variable
的地址初始化ptr
。
解引用指针
*ptr
// 访问存储在ptr
中内存地址的值。
正在加载...
引用概念和语法
引用是现有变量的别名(另一个名称)。一旦引用被初始化为一个变量,它就不能被重新设置以引用另一个变量。引用通常用于通过引用将参数传递给函数。
声明和初始化引用
int& ref = variable;
// 声明一个引用ref
并将其绑定到variable
。
正在加载...
指针算术运算
指针算术运算涉及对指针执行算术运算。它主要用于数组。
ptr + n
:将指针向前移动n
个元素(而不是n
个字节)。ptr - n
:将指针向后移动n
个元素。ptr1 - ptr2
:计算ptr1
和ptr2
之间的元素数量。
正在加载...
函数指针
函数指针是指向函数内存地址的指针。它允许你间接调用函数、将函数作为参数传递或将它们存储在数据结构中。
正在加载...
指针和引用之间的差异
特性 | 指针 | 引用 |
---|---|---|
初始化 | 可以不初始化声明 (但危险) | 必须在声明时初始化 |
空值 | 可以是 nullptr (或 NULL ) | 不能为空 |
重新赋值 | 可以重新赋值以指向不同的变量 | 不能重新设置 (始终引用相同的变量) |
内存地址 | 存储内存地址 | 是别名;不存储自己的地址 (概念上) |
解引用 | 需要 * 才能解引用 | 不需要明确的解引用运算符 (直接使用) |
常见指针错误
- 悬空指针: 指向已释放内存的指针。
- 野指针: 未初始化且指向任意内存位置的指针。
- 空指针解引用: 尝试解引用
nullptr
,导致程序崩溃。 - 内存泄漏: 忘记
delete
动态分配的内存(模块 2 中已涵盖)。
与 JavaScript 引用的比较
JavaScript 没有 C++ 意义上的明确指针或引用。相反,持有对象(包括数组和函数)的 JavaScript 变量存储对这些对象的引用。这些引用由 JavaScript 引擎的垃圾回收器管理。
- 无手动内存管理: 你不需要在 JavaScript 中
new
或delete
对象;GC 会处理它。 - 无指针算术运算: 你不能对 JavaScript 引用执行算术运算。
- 引用可以重新赋值: 与 C++ 引用不同,JavaScript 引用可以重新赋值以指向不同的对象。
本质上,JavaScript 的对象引用在某种程度上类似于 C++ 指向对象的指针,但具有自动内存管理,并且无法执行指针算术运算或直接内存访问。
练习题:
- 解释 C++ 指针和 C++ 引用之间核心差异。何时会选择使用其中一个?
- 编写一个 C++ 函数,该函数接受一个整数指针作为参数,将其指向的值增加 5,然后打印新值。演示如何在
main
中调用此函数。 - 什么是悬空指针,以及如何在 C++ 中避免创建它?
项目构想:
- 使用原始指针在 C++ 中实现一个简单的动态数组(类似于
std::vector
)。你的实现应包括添加元素、移除元素、调整数组大小和按索引访问元素的函数。密切注意内存分配和释放,以防止内存泄漏和悬空指针。