C++ 对象指针

30 May 2025 | 9 分钟阅读

在 C++ 中,对象指针允许我们通过内存地址引用和操作类对象。它是动态内存分配、高效传递对象给函数、实现 多态 以及处理链表和树等数据结构的重要特性。

C++ 中的对象指针是一个包含对象内存地址的变量。指针提供对内存项的间接访问和控制。当我们需要为对象动态分配内存、构建链表或树,或者通过引用将对象传递给方法而不创建副本时,指针尤其有用。

对象指针的行为与变量指针完全相同。只是这里存储的是对象的地址,而不是变量的地址。当在 main 函数中创建类对象时,指针变量的声明方式与变量本身相似。创建对象指针时,不建议使用数据类型。相反,我们必须使用对象指针的类名。使用指针在 main 函数中调用类成员函数时,必须使用 -> 符号。

声明对象指针

我们使用对象的类名后跟一个星号 (*) 和指针名称来声明对象指针。

创建对象和指针

对象是使用 new 关键字创建的,它为对象动态分配内存。然后,指针被赋值为新创建对象的内存地址。

通过指针访问对象成员

我们可以使用箭头运算符 (->) 通过指针访问对象的成员(变量和函数)。

解引用指针

我们使用星号 (*) 运算符“解引用”指针,以访问对象本身(而不是其成员)。

删除对象和指针

当我们不再需要动态分配的对象时,使用 delete 关键字释放内存非常重要。

空指针

指针还可以包含一个特殊值 `nullptr`,表示它不指向有效的内存地址。

将指针传递给函数

在 C++ 中,指针常用于通过引用将对象传递给函数,这允许函数修改原始对象。

指针算术

指针算术适用于数组指针,但不一定适用于对象指针。

C++ 对象指针示例

让我们通过一个示例来理解 C++ 中的对象指针。

示例

编译并运行

输出

Data: 42
Data: 42
Data: 99
Data: 0
Data: 10
Data: 20

说明

在此示例中,我们演示了如何使用对象指针、动态内存分配和通过指针修改对象。之后,定义了一个带有构造函数和 display() 方法的 MyClass 类。最后,使用指针动态创建一个对象,并通过解引用和单独的函数访问和修改该对象。

对象指针数组

在 C++ 中,可以创建对象指针数组,这对于高效管理多个对象尤其有用。在 C++ 中,数组 使用索引来访问元素,这允许我们对一组相关数据进行随机访问。这些元素通常存储在连续的内存位置中。数组可以存储基本 数据类型,包括 int、float、double 和 char,以及指向更复杂对象的指针。

语法

它具有以下语法:

C++ 对象指针数组示例

让我们通过一个示例来说明 C++ 中的对象指针数组。

示例

编译并运行

输出

Title: Book 1
Title: Book 2

说明

在此示例中,我们动态创建了两个 Book 对象,通过循环为它们分配了标题,并通过成员函数显示了它们的标题。最后,使用 delete 释放了分配的内存,以防止内存泄漏。

对象的动态内存分配

在 C++ 中,当系统在编译时无法确定对象的数量时,为对象进行 动态内存分配 非常有用。C++ 使用 new 运算符为对象提供内存并返回指向它的指针。

C++ 对象动态内存分配示例

让我们通过一个示例来说明 C++ 中对象的动态内存分配。

示例

编译并运行

输出

Name: Alice, Age: 25

说明

在此示例中,我们使用指针 p 动态创建了一个 Person 对象。使用 new 在运行时为对象分配内存,并为其成员(name 和 age)赋值。之后,调用 display() 函数打印数据。最后,使用 delete 释放分配的内存,防止内存泄漏。

动态内存分配有什么帮助?

在许多情况下都需要动态分配。

  • 当对象集合在编译时可能会发生变化时。
  • 允许在程序执行期间的任何时间创建对象。
  • 在设置链表、树和图等动态数据结构时。
  • 减少程序使用的内存,并更好地管理对象的创建和销毁时间。
  • 这使得应用程序更易于扩展且占用内存更少。

通过指针访问对象成员

当使用动态分配或指针指向对象时,我们可以通过指针的名称访问成员变量。

或者,也可以这样写

但是,由于其简洁性和可读性,推荐使用 ->。

基类指针指向派生类对象

C++ 允许通过使用基类对象指向派生类对象来实现多态。因此,可以使用动态方法分派调用虚函数。

C++ 基类指针指向派生类对象示例

让我们通过一个示例来说明 C++ 中基类指针指向派生类对象。

示例

编译并运行

输出

Dog barks

说明

在此示例中,我们创建了一个 Animal 基类,它有一个虚函数 speak(),还有一个 Dog 派生类,它重写了 speak() 函数。之后,在 main() 函数中,一个 Animal* 指针 (a) 指向一个派生的 Dog 类 (d)。

C++ 对象指针的优势

C++ 对象指针的几个优势如下:

  • 它支持动态内存分配,使内存使用更轻松高效。
  • 它支持运行时多态,有助于根据实时事件设置行为。
  • 它支持创建动态数据结构,包括链表、树和图。
  • 在将对象传递给函数时,它减少了复制整个对象的需要。
  • 它允许在堆上创建对象,使其比函数存活时间更长。

C++ 对象指针的挑战

C++ 对象指针的几个挑战如下:

  • 虽然指针功能强大,但使用不当可能导致错误。
  • 常见的陷阱包括:
  • 任何未被注意到的动态分配的内存最终都会导致内存泄漏。
  • 如果我们删除了一个对象并尝试使用它占用的内存,就会出现悬空指针错误。
  • 解引用、访问和空指针可能导致程序在运行时崩溃。

结论

在 C++ 中,对象指针发挥着至关重要的作用,能够实现动态行为、内存效率以及面向对象设计原则的实现。它提供了重要的功能,包括运行时多态和动态对象管理。然而,对其使用需要谨慎处理,以避免常见的陷阱,如内存泄漏和悬空指针。通过学习如何使用对象指针,开发人员可以使 C++ 应用程序更灵活、更高效。

C++ 对象指针选择题

1) 如果为对象分配了新内存但从未删除它,会发生什么?

  1. 程序立即崩溃
  2. 最后,对象会自动删除。
  3. 将发生内存泄漏
  4. 在此情况下,对象将保持不动。
 

答案: c) 将发生内存泄漏


2) 使用对象指针时,常见的陷阱有哪些?

  1. 对同一个指针使用 delete 关键字超过一次
  2. 应用箭头运算符
  3. 使用动态内存
  4. 选择私有成员
 

答案: a) 对同一个指针使用 delete 关键字超过一次


3) 如何正确描述基类指针与派生类对象的关系?

  1. 基类指针无法指向派生类对象
  2. 基类指针可以指向派生类对象,但只能调用基类方法,除非使用了虚函数
  3. 通常,基类指针会调用派生类中定义的方法。
  4. 您必须使用显式转换将基类指针转换为派生类。
 

答案: b) 基类指针可以指向派生类对象,但只能调用基类方法,除非使用了虚函数


4) 为什么我们通常在 C++ 中将基类指针分配给派生类对象?

  1. 以减少内存使用量
  2. 以确保不需要虚函数
  3. 通过虚函数实现运行时多态
  4. 仅允许派生类调用基类方法
 

答案: c) 通过虚函数实现运行时多态


5) 考虑以下代码片段。输出将是什么?

  1. 编译错误
  2. 无输出
  3. 运行时错误
  4. Demo::show()
 

答案: d) Demo::show()