【C++系列】指针对象和对象指针的区别

简介: 这段内容介绍了C++中`ListNode`对象和指针的两种使用方式以及它们的区别。首先,`ListNode dummy(0); ListNode* cur = &dummy;创建了一个`ListNode`对象`dummy`在栈上,`cur`是`dummy`的地址。而`ListNode* dummy = new ListNode(0); ListNode* cur = dummy;`则在堆上分配了一个`ListNode`,`dummy`和`cur`都是指向该对象的指针。使用`&dummy`作为虚拟头节点简化链表操作,避免特殊处理。栈分配内存自动管理但生命周期受限,堆分配内存需手动释放且速度较慢。

ListNode dummy(0);ListNode* cur = &dummy; 中,& 是取地址运算符,用来获取变量 dummy 的地址。具体如下:

  • ListNode dummy(0);:创建了一个类型为 ListNode 的对象 dummy,其值初始化为 0
  • &dummy:取 dummy 对象的地址。& 运算符用于获取变量的内存地址。
  • ListNode* cur = &dummy;:声明了一个指向 ListNode 类型的指针 cur,并将其初始化为指向 dummy 的地址。

ListNode* dummy = new ListNode(0); ListNode* cur = dummy; 中,dummy 是链表指针。具体如下:

  • ListNode* dummy = new ListNode(0);:创建了一个类型为 ListNode* 的链表指针dummy,其值初始化为 ListNode(0)
  • new ListNode(0):实例化一个ListNode(0) 对象。
  • ListNode* cur = dummy;:声明了一个 ListNode 类型的指针 cur,并将其初始化为 dummy 指针。

为什么使用 &dummy

使用 &dummy 主要是为了简化链表的操作。具体来说:

  1. 简化链表操作
  • dummy 是一个虚拟头节点,它的存在使得我们不必处理链表头部的特殊情况(比如在空链表上插入第一个节点,或者在链表头部插入新节点)。
  • 通过使用 dummy,所有插入操作都可以统一处理,不需要额外的条件判断。
  1. 指针操作
  • cur 是一个指针,用于遍历和构建新链表。
  • cur 初始化为 dummy 的地址,这样在向链表中添加第一个节点时,dummy.next 可以直接指向新节点,并且后续操作都可以通过更新 cur 来进行。

区别

  1. 内存分配方式
  • ListNode dummy(0); 是在栈上分配的内存。栈上的内存会在超出作用域时自动释放。
  • ListNode* dummy = new ListNode(0); 是在堆上分配的内存。堆上的内存不会自动释放,需要手动调用 delete 来释放,防止内存泄漏。
  1. 指针的使用
  • ListNode dummy(0); ListNode* cur = &dummy; 这里 dummy 是一个对象,cur 是指向 dummy 的指针。
  • ListNode* dummy = new ListNode(0); ListNode* cur = dummy; 这里 dummy 本身就是一个指针,指向堆上的 ListNode 对象,cur 也指向同一个对象。

优缺点

在栈上分配内存

优点

  • 自动管理内存:函数退出时,栈上的内存会自动释放,无需手动管理。
  • 更快的内存分配和释放:栈上的内存操作通常比堆上的快。

缺点

  • 生命周期受限:栈上的对象在函数返回后就被释放,不适合需要在函数外部长期使用的对象。

在堆上分配内存

优点

  • 生命周期灵活:可以手动控制对象的生命周期,适合需要在函数外部长期使用的对象。

缺点

  • 手动管理内存:需要手动释放内存,否则会导致内存泄漏。
  • 相对较慢的内存分配和释放:堆上的内存操作通常比栈上的慢。

在 C++ 中,.-> 操作符用于访问对象的成员:

  • . 操作符用于直接访问对象的成员。
  • -> 操作符用于通过指针访问对象的成员。

区别

  • dummy.nextdummy 是一个对象,通过 . 操作符直接访问 dummy 的成员 next
  • dummy->nextdummy 是一个指向对象的指针,通过 -> 操作符访问指针指向的对象的成员 next

具体示例

栈上分配对象

ListNode dummy(0);       // dummy 是一个对象
ListNode* cur = &dummy;  // cur 是指向 dummy 的指针
cur->next = new ListNode(1);  // 通过 cur 指针访问 next 成员
ListNode* head = dummy.next;  // 直接通过对象 dummy 访问 next 成员

在这个例子中:

  • dummy 是一个 ListNode 对象,可以直接使用 dummy.next 访问其成员。
  • cur 是一个指向 dummy 的指针,使用 cur->next 访问 dummy 的成员。

堆上分配对象

ListNode* dummy = new ListNode(0);  // dummy 是一个指向 ListNode 对象的指针
ListNode* cur = dummy;  // cur 和 dummy 都是指向同一对象的指针
cur->next = new ListNode(1);  // 通过 cur 指针访问 next 成员
ListNode* head = dummy->next;  // 通过 dummy 指针访问 next 成员

在这个例子中:

  • dummy 是一个指向 ListNode 对象的指针,需要使用 dummy->next 访问其成员。
  • cur 同样是一个指向 ListNode 对象的指针,使用 cur->next 访问其成员。

总结

在使用栈上分配的对象时,使用 . 操作符访问成员,因为我们直接处理的是对象本身。而在使用堆上分配的对象时,使用 -> 操作符访问成员,因为我们处理的是指向对象的指针。

相关文章
|
5月前
|
编译器 C++ 开发者
【C++篇】深度解析类与对象(下)
在上一篇博客中,我们学习了C++的基础类与对象概念,包括类的定义、对象的使用和构造函数的作用。在这一篇,我们将深入探讨C++类的一些重要特性,如构造函数的高级用法、类型转换、static成员、友元、内部类、匿名对象,以及对象拷贝优化等。这些内容可以帮助你更好地理解和应用面向对象编程的核心理念,提升代码的健壮性、灵活性和可维护性。
|
20天前
|
算法 Java 数据库连接
Java 与 C++ 区别深入剖析及应用实例详解
本文深入剖析了Java和C++两种编程语言的区别,从编译与执行机制、面向对象特性、数据类型与变量、内存管理、异常处理等方面进行对比,并结合游戏开发、企业级应用开发、操作系统与嵌入式开发等实际场景分析其特点。Java以跨平台性强、自动内存管理著称,适合企业级应用;C++则因高性能和对硬件的直接访问能力,在游戏引擎和嵌入式系统中占据优势。开发者可根据项目需求选择合适语言,提升开发效率与软件质量。附面试资料链接:[点此获取](https://pan.quark.cn/s/4459235fee85)。
55 0
|
4月前
|
编译器 C++
类和对象(中 )C++
本文详细讲解了C++中的默认成员函数,包括构造函数、析构函数、拷贝构造函数、赋值运算符重载和取地址运算符重载等内容。重点分析了各函数的特点、使用场景及相互关系,如构造函数的主要任务是初始化对象,而非创建空间;析构函数用于清理资源;拷贝构造与赋值运算符的区别在于前者用于创建新对象,后者用于已存在的对象赋值。同时,文章还探讨了运算符重载的规则及其应用场景,并通过实例加深理解。最后强调,若类中存在资源管理,需显式定义拷贝构造和赋值运算符以避免浅拷贝问题。
|
4月前
|
存储 编译器 C++
类和对象(上)(C++)
本篇内容主要讲解了C++中类的相关知识,包括类的定义、实例化及this指针的作用。详细说明了类的定义格式、成员函数默认为inline、访问限定符(public、protected、private)的使用规则,以及class与struct的区别。同时分析了类实例化的概念,对象大小的计算规则和内存对齐原则。最后介绍了this指针的工作机制,解释了成员函数如何通过隐含的this指针区分不同对象的数据。这些知识点帮助我们更好地理解C++中类的封装性和对象的实现原理。
|
5月前
|
编译器 C语言 C++
类和对象的简述(c++篇)
类和对象的简述(c++篇)
|
4月前
|
编译器 C++
类和对象(下)C++
本内容主要讲解C++中的初始化列表、类型转换、静态成员、友元、内部类、匿名对象及对象拷贝时的编译器优化。初始化列表用于成员变量定义初始化,尤其对引用、const及无默认构造函数的类类型变量至关重要。类型转换中,`explicit`可禁用隐式转换。静态成员属类而非对象,受访问限定符约束。内部类是独立类,可增强封装性。匿名对象生命周期短,常用于临时场景。编译器会优化对象拷贝以提高效率。最后,鼓励大家通过重复练习提升技能!
|
5月前
|
安全 编译器 C语言
【C++篇】深度解析类与对象(中)
在上一篇博客中,我们学习了C++类与对象的基础内容。这一次,我们将深入探讨C++类的关键特性,包括构造函数、析构函数、拷贝构造函数、赋值运算符重载、以及取地址运算符的重载。这些内容是理解面向对象编程的关键,也帮助我们更好地掌握C++内存管理的细节和编码的高级技巧。
|
5月前
|
存储 程序员 C语言
【C++篇】深度解析类与对象(上)
在C++中,类和对象是面向对象编程的基础组成部分。通过类,程序员可以对现实世界的实体进行模拟和抽象。类的基本概念包括成员变量、成员函数、访问控制等。本篇博客将介绍C++类与对象的基础知识,为后续学习打下良好的基础。
|
1月前
|
人工智能 机器人 编译器
c++模板初阶----函数模板与类模板
class 类模板名private://类内成员声明class Apublic:A(T val):a(val){}private:T a;return 0;运行结果:注意:类模板中的成员函数若是放在类外定义时,需要加模板参数列表。return 0;
43 0
|
1月前
|
存储 编译器 程序员
c++的类(附含explicit关键字,友元,内部类)
本文介绍了C++中类的核心概念与用法,涵盖封装、继承、多态三大特性。重点讲解了类的定义(`class`与`struct`)、访问限定符(`private`、`public`、`protected`)、类的作用域及成员函数的声明与定义分离。同时深入探讨了类的大小计算、`this`指针、默认成员函数(构造函数、析构函数、拷贝构造、赋值重载)以及运算符重载等内容。 文章还详细分析了`explicit`关键字的作用、静态成员(变量与函数)、友元(友元函数与友元类)的概念及其使用场景,并简要介绍了内部类的特性。
111 0