「C++系列」指针

news2024/9/29 23:32:41

文章目录

  • 一、指针的定义
  • 二、指针的基本概念
    • 1. 基本概念
    • 2. 案例代码
      • 示例 1:基本指针使用
      • 示例 2:指针与数组
    • 3. 注意事项
  • 三、指针的用途
    • 1. 指针的用途
    • 2. 案例代码
      • 案例1. 动态内存分配
      • 案例2. 函数参数(通过指针修改值)
      • 案例3. 数组和字符串
      • 案例4. 链表节点(简化示例)
  • 四、指针的注意事项
    • 1. 注意事项
    • 2. 详细案例代码
      • 动态内存分配与释放
      • 函数参数传递
      • 指针与数组
  • 五、相关链接

一、指针的定义

指针是一个变量,其值为另一个变量的地址,即,内存位置的直接地址。就像其他变量或常量一样,您必须在使用指针存储其他变量地址之前,对其进行声明。

二、指针的基本概念

C++ 中的指针是编程中的一个核心概念,它允许你直接访问和操作内存地址。以下是关于 C++ 指针的一些基本概念和案例代码。

1. 基本概念

  1. 定义指针:指针变量通过类型名后加上星号 * 来定义。例如,int* ptr; 定义了一个名为 ptr 的指针变量,它可以存储一个 int 类型变量的地址。

  2. 赋值给指针:你可以将一个变量的地址赋给指针。使用 & 操作符来获取变量的地址。例如,int var = 10; int* ptr = &var; 这里,&var 是变量 var 的地址,它被赋给了指针 ptr

  3. 通过指针访问值:使用解引用操作符 * 来访问指针指向的值。例如,*ptr 会访问 ptr 指向的内存地址中的值。

  4. 指针的算术运算:对于指向数组元素的指针,你可以进行算术运算(如递增 ++ 或递减 --),这会改变指针指向的数组元素。

  5. 空指针:未初始化的指针可能指向任意内存地址,这是不安全的。通常将指针初始化为 nullptr(或 NULL,但在 C++11 及更高版本中推荐使用 nullptr),以表示它不指向任何有效的内存地址。

  6. 指针与数组:在 C++ 中,数组名通常被当作指向数组第一个元素的指针。

2. 案例代码

示例 1:基本指针使用

#include <iostream>
using namespace std;

int main() {
    int var = 20; // 定义一个整型变量
    int* ptr;     // 定义一个整型指针

    // 让指针指向变量的地址
    ptr = &var;

    // 通过指针访问变量的值
    cout << "Value of var through pointer: " << *ptr << endl;

    // 修改指针指向的值
    *ptr = 100;

    // 再次通过指针访问变量的值
    cout << "New value of var through pointer: " << *ptr << endl;

    return 0;
}

示例 2:指针与数组

#include <iostream>
using namespace std;

int main() {
    int arr[] = {10, 20, 30, 40, 50}; // 定义一个整型数组
    int* ptr;                        // 定义一个整型指针

    // 让指针指向数组的第一个元素
    ptr = arr;

    // 通过指针遍历数组
    for (int i = 0; i < 5; i++) {
        cout << *(ptr + i) << " "; // 使用指针算术访问数组元素
    }
    cout << endl;

    return 0;
}

在这个例子中,ptr 最初指向数组的第一个元素(即 arr[0])。通过递增 ptr(实际上是 ptr + i),我们可以遍历数组中的每个元素。注意,这里的 ptr + i 实际上是对指针进行算术运算,使其指向数组中的第 i+1 个元素(因为数组索引从 0 开始)。

3. 注意事项

  • 指针操作需要谨慎,因为错误的指针算术或解引用可能导致未定义行为,如访问无效内存或程序崩溃。
  • 在使用指针时,务必确保指针指向有效的内存地址,并在不再需要时释放动态分配的内存(如果使用 newmalloc 分配了内存)。
  • 指针类型必须与其指向的数据类型匹配,以确保类型安全。

三、指针的用途

C++ 中的指针具有多种用途,从动态内存管理到数组和字符串的处理,再到复杂数据结构的实现,指针都扮演着至关重要的角色。下面我将列举一些指针的用途,并提供相应的案例代码。

1. 指针的用途

  1. 动态内存分配
    指针可以与 newdelete 操作符一起使用,在堆上动态地分配和释放内存。

  2. 函数参数
    通过将指针作为函数参数传递,函数可以直接修改传递给它的变量的值。

  3. 数组和字符串
    在 C++ 中,数组名通常被视为指向数组第一个元素的指针,而字符串(字符数组)也常通过字符指针来处理。

  4. 链表、树等数据结构的实现
    指针是实现链表、树等复杂数据结构的关键,因为它们允许节点之间建立直接的连接。

  5. 函数指针
    函数指针可以指向函数,使得函数可以作为参数传递给其他函数,或者作为其他函数的返回值。

2. 案例代码

案例1. 动态内存分配

#include <iostream>
using namespace std;

int main() {
    int* ptr = new int; // 动态分配一个整型变量的内存
    *ptr = 10; // 通过指针赋值

    cout << "Value of dynamically allocated int: " << *ptr << endl;

    delete ptr; // 释放内存

    return 0;
}

案例2. 函数参数(通过指针修改值)

#include <iostream>
using namespace std;

void modifyValue(int* ptr) {
    *ptr = 100; // 直接修改指针指向的值
}

int main() {
    int var = 20;
    modifyValue(&var); // 传递变量的地址

    cout << "Value of var after modification: " << var << endl;

    return 0;
}

案例3. 数组和字符串

#include <iostream>
using namespace std;

int main() {
    char str[] = "Hello, World!"; // 字符数组(字符串)
    char* ptr = str; // 指针指向字符串的首字符

    // 通过指针遍历字符串
    while (*ptr != '\0') { // 字符串以空字符 '\0' 结尾
        cout << *ptr++; // 输出当前字符,并将指针移动到下一个字符
    }

    cout << endl;

    return 0;
}

案例4. 链表节点(简化示例)

#include <iostream>
using namespace std;

// 链表节点的简单定义
struct ListNode {
    int value;
    ListNode* next;

    ListNode(int x) : value(x), next(nullptr) {}
};

int main() {
    // 创建链表:1 -> 2 -> 3
    ListNode* head = new ListNode(1);
    head->next = new ListNode(2);
    head->next->next = new ListNode(3);

    // 遍历链表并打印值(简化版,未释放内存)
    ListNode* current = head;
    while (current != nullptr) {
        cout << current->value << " ";
        current = current->next;
    }

    cout << endl;

    // 注意:在实际应用中,应该释放链表节点所占用的内存

    return 0;
}

注意:在上面的链表示例中,我为了简化而没有释放分配的内存。在实际应用中,你应该在链表不再需要时遍历链表并释放每个节点所占用的内存,以避免内存泄漏。

四、指针的注意事项

在C++中,指针是一种强大的工具,它允许直接访问和操作内存地址。然而,由于这种直接性,指针的使用也需要格外小心,以避免程序崩溃、内存泄漏等问题。以下是C++指针的注意事项及详细案例代码。

1. 注意事项

  1. 初始化指针
  • 在使用指针之前,一定要确保它被正确初始化。未初始化的指针可能指向任何随机的内存地址,这可能导致程序崩溃或不可预测的行为。
  • 示例代码(未初始化指针的潜在问题):
int* ptr; // 未初始化
*ptr = 10; // 可能导致程序崩溃,因为ptr可能指向无效内存
  1. 检查空指针
  • 在解引用指针之前,检查它是否为NULL(或在C++11及以后使用nullptr)是一个好习惯。尝试解引用空指针将导致程序崩溃。
  • 示例代码:
int* ptr = nullptr;
if (ptr != nullptr) {
    std::cout << *ptr << std::endl; // 不会执行,因为ptr是nullptr
}
  1. 避免内存泄漏
  • 动态分配的内存(使用newmalloc)必须在不再需要时释放(使用deletefree)。否则,程序将占用越来越多的内存,最终导致内存泄漏。
  • 示例代码:
int* ptr = new int(10);
// ... 使用ptr ...
delete ptr; // 释放内存
  1. 释放内存后设置指针为NULL
  • 释放内存后,将指针设置为NULL(或在C++11及以后使用nullptr)是一个好习惯,这有助于避免悬挂指针(dangling pointers)的问题。
  • 示例代码:
int* ptr = new int(10);
// ... 使用ptr ...
delete ptr;
ptr = nullptr; // 防止悬挂指针
  1. 指针类型匹配
  • 确保指针的类型与它所指向的数据类型相匹配。例如,一个int类型的指针不应该用来指向float类型的数据。
  1. 避免指针运算错误
  • 指针的加减运算不是简单的数学加减,而是根据指针类型的大小来移动的。例如,int* ptr; ptr++; 实际上是将ptr向后移动了一个int类型的大小(通常是4个字节,但这也取决于编译器和平台)。
  1. 使用智能指针
  • 在C++中,可以使用智能指针(如std::unique_ptrstd::shared_ptr)来自动管理内存,从而减少内存泄漏的风险。

2. 详细案例代码

动态内存分配与释放

#include <iostream>
using namespace std;

int main() {
    int* ptr = new int(10); // 动态分配内存并初始化
    cout << "Value: " << *ptr << endl;

    // ... 使用ptr ...

    delete ptr; // 释放内存
    ptr = nullptr; // 防止悬挂指针

    return 0;
}

函数参数传递

#include <iostream>
using namespace std;

void modifyValue(int* ptr) {
    *ptr = 20; // 修改指针指向的值
}

int main() {
    int value = 10;
    modifyValue(&value); // 传递value的地址
    cout << "Modified Value: " << value << endl; // 输出: Modified Value: 20

    return 0;
}

指针与数组

#include <iostream>
using namespace std;

int main() {
    int arr[] = {1, 2, 3, 4, 5};
    int* ptr = arr; // 指针指向数组的第一个元素

    for (int i = 0; i < 5; i++) {
        cout << *ptr++ << " "; // 输出当前值并移动指针
    }
    cout << endl; // 输出: 1 2 3 4 5

    return 0;
}

在这里插入图片描述

五、相关链接

  1. Visual Studio Code下载地址
  2. Sublime Text下载地址
  3. 「C++系列」C++简介、应用领域
  4. 「C++系列」C++ 基本语法
  5. 「C++系列」C++ 数据类型
  6. 「C++系列」C++ 变量类型
  7. 「C++系列」C++ 变量作用域
  8. 「C++系列」C++ 常量知识点-细致讲解
  9. 「C++系列」C++ 修饰符类型
  10. 「C++系列」一篇文章说透【存储类】
  11. 「C++系列」一篇文章讲透【运算符】
  12. 「C++系列」循环
  13. 「C++系列」判断
  14. 「C++系列」函数/内置函数
  15. 「C++系列」数字/随机数
  16. 「C++系列」数组
  17. 「C++系列」字符串

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1980192.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

poky yocto(04):编译在vmware上运行的镜像

编译镜像 bitbake build-appliance-image 得到文件&#xff1a;build-appliance-image-qemux86-64.wic.vmdk 问题的关键来了&#xff0c;如何启动这个东西呢&#xff1f;由名字可知&#xff0c;这是一个vmware的硬盘文件&#xff0c;需要创建一个新的虚拟机加载它。 创建虚拟…

黑神话悟空游戏电脑配置要求 黑神话悟空Steam销量全球两连冠 黑神话悟空苹果笔记本电脑能玩吗 黑神话悟空是什么类型的游戏

相信不少游戏爱好者&#xff0c;近期被《黑神话&#xff1a;悟空》这款游戏刷屏了&#xff0c;备受期待的国产单机大作《黑神话:悟空》将于8月20日全球同步上线&#xff0c;登陆 PC (Steam / Epic / WeGame) 和 PS5 平台。凭借空前的关注度&#xff0c;该游戏有望成为国产游戏行…

sql注入漏洞复现

and 11 正常 and 12 报错 从这就已经说明是sql数字型注入了 上sqlmap验证一下 存在布尔盲注&#xff0c;时间盲注...... 我是在漏洞盒子上提交的&#xff0c;能不能通过看运气吧 下面这个漏洞已经是很久之前的了&#xff0c;现在已经是修复了&#xff0c;当时还是太年轻了...…

文献阅读:扩散波模型的物理信息神经网络

目录 摘要 Abstract 扩散波模型的物理信息神经网络 文献摘要 讨论|结论 理论知识 扩散波动方程&#xff08;曼宁方程&#xff09; 梯度停止&#xff08;Stop-gradient&#xff09;技术 时分PINN(TPINN) 新结构(fPINN) 实验设置 稳定流问题 等速和扩散问题 非线性速…

基于STM32的简易音频播放系统

目录 引言环境准备工作 硬件准备软件安装与配置系统设计 系统架构硬件连接代码实现 初始化代码音频播放代码应用场景 简易音频播放语音提示系统常见问题及解决方案 常见问题解决方案结论 1. 引言 音频播放系统在日常生活中有着广泛的应用&#xff0c;从简单的语音提示到复杂…

基于Transformer的语音识别与音频分类

重磅推荐专栏: 《大模型AIGC》 《课程大纲》 《知识星球》 本专栏致力于探索和讨论当今最前沿的技术趋势和应用领域,包括但不限于ChatGPT和Stable Diffusion等。我们将深入研究大型模型的开发和应用,以及与之相关的人工智能生成内容(AIGC)技术。通过深入的技术解析和实践经…

如果我的发明有修改,需要如何处理?

如果我的发明有修改&#xff0c;需要如何处理&#xff1f;

近期关于云服务器window server 2012屏蔽游戏加速器/IP加速器模拟IP连接限制策略

winr 打开运行 输入 gpedit.msc 找到本地组策略编辑器的对应设置 设置启用即可。

【redis 第七篇章】动态字符串

一、概述 string 类型底层实现的简单动态字符串 sds&#xff0c;是可以修改的字符串。它采用预分配冗余空间的方式来减少内存的频繁分配。 二、SDS动态字符串 动态字符串 是以 \0 为分隔符。最大容量 是 redis 主动分配的一块内存空间&#xff0c;实际存储内容 是具体的存的数…

BACnet 调试工具 工程师必备

文章目录 BACnet 调试工具 工程师必备主要功能软件截图 BACnet 调试工具 工程师必备 官网地址 BACnet&#xff08;Building Automation and Control Networks&#xff09;是由美国采暖、制冷与空调工程师学会&#xff08;American Society of Heating, Refrigerating and Air…

【网络层】IP报文解析和网段划分

文章目录 网络层的作用IP协议协议报头格式网段划分DHCPCIDR划分方案 IP地址的数量限制私有IP地址和公网IP地址LAN和WAN 路由 网络层的作用 前面学习了应用层和传输层&#xff0c;应用层的作用是为用户和应用程序提供网络服务&#xff0c;传输层的作用是提供端口到端口的通信服…

Android 10.0 系统默认蓝牙打开状态栏显示蓝牙图标功能实现

1.前言 在10.0的系统rom定制化开发过程中,在默认系统中,打开蓝牙开关的时候不会状态栏不会显示蓝牙图标,而只有 蓝牙连接成功后会显示蓝牙图标,客户开发需要要求在蓝牙打开的时候在状态栏就显示蓝牙图标,接下来分析下 相关的状态栏图标显示流程,然后实现相关功能 2.系统…

模块的介绍

一、模块的基本介绍 1、模块是什么&#xff1f; 1&#xff09;模块是一个py文件&#xff0c;后缀名.py 2&#xff09;模块可以定义函数、类和变量&#xff0c;模块里也可能包含可执行的代码 2、模块的作用有哪些&#xff1f; 1&#xff09;当函数、类、变量很多时&#xf…

java基础--字符串用法

一、前言&#xff08;在java中字符串的重要性&#xff09; 在 Java 编程中&#xff0c;字符串&#xff08;String&#xff09;的重要性不言而喻&#xff0c;它几乎贯穿于所有的应用程序和系统中。以下是 Java 中字符串重要性的几个方面&#xff1a; 1. 数据表示和处理 文本数…

使用PXE和kickstart完成自动化批量主机的安装

本实验采用的版本为rhel7.9 kickstart&#xff1a; 首先写一个kickstart脚本 安装脚本工具 配置自动化脚本 下载http服务用来共享脚本 yum install httpd -y systemctl enable httpd --now 实验的过程中把防火墙和selinux都关闭 配置自动化脚本 创建一个软链接使得用户访…

集团ERP信息化项目实施方案(可编辑82页PPT)

引言&#xff1a;在当前信息化快速发展的时代&#xff0c;集团企业面临着日益增长的业务复杂性和数据管理挑战。为了提升集团的整体运营效率、加强数据集成与共享、优化业务流程&#xff0c;我们决定实施ERP&#xff08;企业资源计划&#xff09;信息化项目。 方案介绍&#x…

最新口型同步技术EchoMimic部署

EchoMimic是由蚂蚁集团推出的一个 AI 驱动的口型同步技术项目&#xff0c;能够通过人像面部特征和音频来帮助人物“对口型”&#xff0c;生成逼真的动态肖像视频。 EchoMimic的技术亮点在于其创新的动画生成方法&#xff0c;它不仅能够通过音频和面部关键点单独驱动图像动画&a…

翻译: 可视化深度学习反向传播原理二

顺便一提 这有一点点像描述生物中 神经元的网络如何学习的一个理论 “赫布理论” 总结起来就是“一同激活的神经元关联在一起” 这里 权重的最大增长 即连接变得更强的部分 就会发生在已经最活跃的神经元 和想要更多激发的神经元之间 可以说 看见一个“2”时激发的神经元 会和…

【Git】git 不跟踪和gitignore区别

文章目录 不跟踪&#xff08;Untracked&#xff09;&#xff1a;.gitignore 文件&#xff1a;总结 在 Git 中&#xff0c;不跟踪&#xff08;untracked&#xff09;和 .gitignore 文件有不同的作用和用途&#xff1a; 不跟踪&#xff08;Untracked&#xff09;&#xff1a; 不…

【Material-UI】Autocomplete中的高亮功能(Highlights)详解

文章目录 一、简介二、实现高亮功能示例代码代码解释 三、实际应用场景1. 搜索功能2. 表单自动完成 四、总结 在现代Web开发中&#xff0c;提供清晰的用户反馈是提升用户体验的重要组成部分。Material-UI的Autocomplete组件通过高亮功能&#xff0c;帮助用户快速识别搜索结果中…