C++-指针

在C++中,指针是至关重要的组成部分。它是C++语言最强大的功能之一,也是最棘手的功能之一。 指针具有强大的能力,其本质是协助程序员完成内存的直接操纵。

指针:特定类型数据在内存中的存储地址,即内存地址。

指针变量的定义语法: 先声明,后赋值:

变量类型 * 指针变量名;       // 声明
指针变量名 = 内存地址值;     // 赋值

int num = 10;
int * p;		// 声明
p = #	// 赋值

- 变量类型(如上int)表示,指针(内存地址)指向的内存区域,存放的是整型数据              

- *符号有两种含义:             

- 声明时:*p,表示变量p,是指针变量(存的是内存地址)             

- 使用时:*p,表示取指针p执行内存区域的数据              

- &符号表示取变量内存地址,是一个取内存地址的单目操作符

野指针和空指针

野指针:被声明但未初始化(赋值)的指针。这个指针会指向随机的内存空间,可能导致未知问题。

int * p;    // 声明指针(分配了8字节空间), p是野指针因为未被赋值
*p = 10;    // 将10赋予指针p所指向的空间

*p = 10;是向未知的、随机的4字节内存区域,修改存储值为10

为避免野指针,应养成良好的变成习惯,及时初始化,或将指针置为空指针更为安全

int * p = NULL;
int * p = nullptr;

指针运算

int num = 10;
int *p = #
cout << p << endl;    // 结果:0x20d1ff6e4;
cout << p++ << endl;    // 结果:0x20d1ff6e8

指针进行加减运算的结果,和指针指向内存区域的数据类型有关,以加法为例:

char 类型指针 +1, 地址+1 (字节)

int 类型指针+1, 地址+4(字节)

double 类型指针+1, 地址+8 (字节)

指针运算

数组对象本身记录的是内存地址(第一个元素地址) 可以通过指针运算,完成使用指针存取数组元素。

int v[] = {1, 2, 3, 4, 5};
int *p = v;
*p = 11;                // 赋值数组第一个元素
*(p+1) = 22;            // 赋值数组第二个元素
*(p+2) = 33;            // 赋值数组第三个元素
cout << *p << endl;     // 取数组第一个元素
cout << *(p+1) << endl; // 取数组第二个元素
cout << *(p+2) << endl; // 取数组第三个元素

动态内存分配

动态内存分配:即由程序员手动的进行内存空间的分配、内存空间的释放等内存管理操作。

C++代码中,变量、数组等对象的创建,是由C++自动分配内存的,称之为(自动)静态内存分配。

(自动)静态内存管理,是不会进行内存空间的自动清理的。(无垃圾回收机制) 我们需要手动的管理内存,即手动分配,用完清理。

手动管理方式:

new运算符申请空间,提供该空间的指针(地址)

delete运算符申请的空间,仅用于new申请的空间

建议:写完new后,立刻写delete,然后再写业务逻辑代码

int * p = new int;      // 申请int类型(4字节)空间
int * p = new double;   // 申请double类型(8字节)空间
delete p;               // 删除申请的空间
int * p = new int[5];   // 申请5元素int数组空间
delete[] p;             // 删除申请的5元素数组空间

优势: 手动控制内存,避免内存空间浪费

劣势: 考验程序员水平,用的好效率高,用不好有反效果

new

new运算符用于申请并分配内存空间 并提供指向该空间的指针(内存地址) 基本语法:

new type 申请普通变量空间

new type[n] 申请数组空间

delete

delete运算符用于释放内存 仅可用于new运算符申请的内存区域

基本语法:

delete 指针 删除普通变量空间

delete[] 指针 删除数组空间

数组元素的插入举例:

#include "iostream"
using namespace std;

/* 在下标1和3插入数字:11和66 */

int main()
{
    // 示例数组
    int * pArr = new int[5] {1, 3, 5, 7, 9};

    // 创建新数组
    int * pNewArr = new int[7];

    // 循环新数组,挨个进行元素填充(非插入的位置,填充老数组元素,插入位置填充新元素)
    int offset = 0;     // 偏移量用来控制新老数组元素的下标对照
    for (int i = 0; i < 7; i++)
    {
        if (i == 1)
        {
            // 走到了下标1,应当执行新元素插入
            pNewArr[i] = 11;
            offset++;       // 每插入一个新元素,offset+1
            continue;
        } else if (i == 3)
        {
            // 走到了下标3,应当执行新元素插入
            pNewArr[i] = 66;
            offset++;       // 每插入一个新元素,offset+1
            continue;
        }

        // 不是插入位置,从老数组中提取元素放入新数组中
        // 公式:老数组的元素下标 + offset = 新数组元素下标
        // 当前循环的i是新数组的元素下标
        pNewArr[i] = pArr[i-offset];
    }

    // 收尾工作
    delete[] pArr;
    pArr = pNewArr;

    // 将新数组的内容输出
    for (int i = 0; i< 7; i++)
    {
        cout << pNewArr[i] << ",";
    }

    return 0;
}

数组元素的删除举例:

#include "iostream"
using namespace std;

int main()
{
    // 示例数组
    int * pArr = new int[5] {1, 3, 5, 7, 9};

    // 创建一个新的数组,将需要保留的复制到新数组中
    int * pNewArr = new int[4];

    // 循环去遍历老的数组,将需要的元素放入新数组中(不要的要跳过)
    for (int i = 0; i < 5; i++)
    {
        if (i == 2)
        {
            continue;
        }

        if (i > 2)
        {
            pNewArr[i-1] = pArr[i];
        }else
        {
            pNewArr[i] = pArr[i];
        }
    }

    // 可选
    delete[] pArr;      // 回收老数组的空间(可选,根据需要来说)

    // 可选
    pArr = pNewArr;     // 将老数组的指针指向新数组的内存空间(可选,根据需要)

    for (int i = 0; i < 4; i++)
    {
        cout << "新数组的元素是:" << pNewArr[i] << endl;
        cout << "新数组的元素是:" << pArr[i] << endl;
    }

    return 0;
}

指针悬挂:

指针指向区域已经被回收(delete),这种问题称之为:指针悬挂。

不要轻易进行指针之间相互赋值

delete回收空间前,确保此空间100%不再被使用

错误示范:

int main()
{   int * p1 = new int;
    int * p2 = p1;  // 将p1赋值给p2
    *p1 = 10;   
    delete p1;
    cout << "p2指针记录的是:" << *p2 << endl;
    return 0;
}

const指针

const是C++关键字,被译为常量,const指针即表示:常量指针。

const用来修饰常量(不可更改),可以配合指针使用 以int为例。

const int * p; 指向常量的指针,即存储值不可变,但指针可修改指向

int * const p = 地址; 常量指针

存储的值可以变 指着不可修改指向 必须初始化指针的地址

const int * const p = 地址; 指向常量的常量指针

存储的值和指针的指向,均不可修改

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【第39天】SQL进阶-SQL设计优化-反范式设计(SQL 小虚竹)

回城传送–》《100天精通MYSQL从入门到就业》 文章目录 零、前言一、练习题目二、SQL思路初始化数据什么是反范式设计例子反范式设计的优点反范式设计的缺点实战中要注意的坑 三、总结四、参考 零、前言 今天是学习 SQL 打卡的第 39 天。 ​ 我的学习策略很简单&#xff0c;…

瓦罗兰特账号怎么注册 瓦罗兰特延迟高用什么加速器

《瓦罗兰特》&#xff08;Valorant&#xff09;是由拳头游戏&#xff08;Riot Games&#xff09;开发并发行的一款免费的多人在线第一人称射击游戏&#xff08;FPS&#xff09;&#xff0c;它结合了传统的硬核射击机制与英雄角色的能力系统&#xff0c;为玩家提供了独特的竞技体…

无忧易售ERP:智慧采购,重塑供应链管理新高度

在当今瞬息万变的商业环境中&#xff0c;高效的采购策略不仅是成本控制的关键&#xff0c;更是企业竞争力的体现。无忧易售ERP&#xff0c;作为一站式企业资源规划解决方案的领航者&#xff0c;专为现代企业量身打造了集成化的采购管理模块&#xff0c;以智能化、自动化的工具为…

适用于Android的最佳数据恢复软件

如果您的 Android 设备崩溃&#xff0c;您需要找到一种方法来取回您的数据。幸运的是&#xff0c;有许多数据恢复程序可以帮助您恢复丢失的文件。有些是免费的&#xff0c;而另一些则需要付费。这是适用于Android设备的最佳数据恢复软件列表。 什么是数据恢复软件&#xff1f; …

python-数据可视化

python-数据可视化 ** 数据可视化指的是通过可视化表示来探索数据&#xff0c;它与数据挖掘**紧密相关&#xff0c;而数据挖掘指的是使用代码来探索数据集的规律和关联。数据集可以是用一行代码就能表示的小型数字列表&#xff0c;也可以是数以吉字节的数据 最流行的工具之一…

eBPF可观测之网络流量控制和管理traffic control浅尝

目录 工程背景 环境准备 安装工具​​​ 安装依赖包 安装C依赖库 操作步骤 目录结构 代码展示 效果展示 拓展提升 工程背景 首先发表一个"暴论" eBPF在可观测方面的应用&#xff0c;就是各种google。 不需要学习内核&#xff0c;只要掌握ebpf开发套路。…

什么是“SQL注入攻击”?如何预防和应对?

一、SQL注入攻击的概念 SQL注入攻击是一种针对数据库驱动的应用程序的攻击技术&#xff0c;其中攻击者通过在应用程序的输入字段中插入或“注入”恶意的SQL代码&#xff0c;试图非法访问、操作或破坏后端数据库。当应用程序不正确地处理用户输入&#xff0c;并将其直接拼接到SQ…

【NumPy】NumPy线性代数模块详解:掌握numpy.linalg的核心功能

&#x1f9d1; 博主简介&#xff1a;阿里巴巴嵌入式技术专家&#xff0c;深耕嵌入式人工智能领域&#xff0c;具备多年的嵌入式硬件产品研发管理经验。 &#x1f4d2; 博客介绍&#xff1a;分享嵌入式开发领域的相关知识、经验、思考和感悟&#xff0c;欢迎关注。提供嵌入式方向…

国产数据库替代加速 助力数字中国建设

5月24日&#xff0c;随着第七届数字中国建设峰会在福州的成功举办&#xff0c;释放数据要素价值、发展新质生产力成为当下热议的话题。 数据作为新型生产要素&#xff0c;是数字化、网络化、智能化的重要基础。北京人大金仓信息技术股份有限公司&#xff08;以下简称人大金仓&a…

如何改变echo在Linux下的输出颜色

文章目录 问题回答常规输出字体加粗斜体字带下划线闪烁效果 参考 问题 我正在尝试使用 echo 命令在终端中打印文本。 我想把文本打印成红色。我该怎么做&#xff1f; 回答 你可以使用 ANSI escape codes 定义控制输出颜色的变量。 ANSI escape codes是一种用于在文本中设置…

动手学深度学习23 LeNet

动手学深度学习23 LeNet 1. LeNet2. 代码3. QA 1. LeNet 两层卷积两层池化两层全连接 卷积就是让每一层shape不断压缩变小【高宽减少】&#xff0c;通道数增多&#xff0c;把特征信息放到不同的通道里面。每一个通道认为是一个模式。然后再做全连接的输入。 2. 代码 impor…

4款让人骄傲的国产软件,功能过于强大,却被误认为是外国佬研发

说到国产软件&#xff0c;许多人可能会有“流氓软件、弹屏广告多、隐藏消费套路”等负面印象。 这种偏见导致一些功能强大、用户友好的国产软件被误认为是外国人开发的。 1、格式工厂 格式工厂是一个很实用的国产格式转换工具&#xff0c;它完全免费且没有广告&#xff0c;不…

大模型实战-动手实现单agent

文章目录 入口cli_main.py工具tools.pyprompt prompt_cn.pyLLM 推理 model_provider.py致谢 agent 的核心思想&#xff1a;不断调用 LLM&#xff08;多轮对话&#xff09;&#xff0c;让 LLM 按照指定的格式&#xff08;例如 json&#xff09;进行回复&#xff0c;提取 LLM 回复…

【LaTex】11 ACM参考文献顺序引用 - 解决 ACM-Reference-Format 顺序不符合论文实际引用顺序的问题

【LaTex】11 ACM参考文献顺序引用 写在最前面解决 ACM-Reference-Format 顺序不符合论文实际引用顺序的问题问题描述问题原因如何解决问题解决方案1&#xff08;更简单&#xff09;解决方案2&#xff08;更自由&#xff09; 小结 &#x1f308;你好呀&#xff01;我是 是Yu欸 …

巧用java8的stream流的.collect(Collectors.toMap(arg1,arg2))

最近公司接手了一个低代码二次开发平台的需求&#xff0c;需要连接多张表的数据然后展示到界面上。 按照java的sql思路&#xff0c;我们直接通过left join去关联表就行了&#xff0c;但是该低代码平台有对sql连表查询有限制&#xff0c;就是有些表它是存在一个domainKey的&…

牛客题霸-SQL大厂面试真题(一)

本文基于前段时间学习总结的 MySQL 相关的查询语法&#xff0c;在牛客网找了相应的 MySQL 题目进行练习&#xff0c;以便加强对于 MySQL 查询语法的理解和应用。 由于涉及到的数据库表较多&#xff0c;因此本文不再展示&#xff0c;只提供 MySQL 代码与示例输出。 以下内容是…

Java | Leetcode Java题解之第101题对称二叉树

题目&#xff1a; 题解&#xff1a; class Solution {public boolean isSymmetric(TreeNode root) {return check(root, root);}public boolean check(TreeNode u, TreeNode v) {Queue<TreeNode> q new LinkedList<TreeNode>();q.offer(u);q.offer(v);while (!q.…

大数据框架总结(全)

☔️ 大数据框架总结&#xff08;全&#xff09; 关注“大数据领航员”&#xff0c;在公众号号中回复关键字【大数据面试资料】&#xff0c;即可可获取2024最新大数据面试资料的pdf文件 一. Hadoop HDFS读流程和写流程 HDFS写数据流程 &#xff08;1&#xff09;客户端通过…

【ARM+Codesys案例】T3/RK3568/树莓派+Codesys锂电池测试设备控制解决方案

锂电池诞生于上世纪60年代&#xff0c;90年代开始由日本索尼公司实现商业化。锂离子电池凭借快速充放电、长循环寿命、无记忆效应等众多优点&#xff0c;成为当今数码产品及电动汽车大规模应用的第一选择。与镍氢电池、铅酸电池相比&#xff0c;锂电池可以存储更多电能。现在&a…

ECOLOGY9解决明细表数据按需显示或隐藏

ECOLOGY9:由于领导需要查看完整的明细表数据&#xff0c;没有启用分页功能&#xff0c;导致大领导查看时又出现几百行的数据&#xff0c;影响使用体验。需求&#xff1a;只看正常表单数据&#xff0c;明细表数据&#xff0c;默认不显示&#xff0c;需要查看时再打开。 实现&am…