C++ 编程基础(3)数据类型 | 3.1、指针
文章目录
- 一、指针
- 1、定义
- 2、解引用
- 3、指针的运算
- 4、指针与数组
- 4.1、通过指针操作数据
- 4.2、指针与数组名的区别
- 4.3、数组名作为函数形参
- 5、指针作为函数参数
- 5.1、作为函数参数
- 5.2、常指针与指针常量
- 6、指针与动态内存分配
- 7、注意事项
- 8、总结
前言:
在C++编程中,指针是一种非常重要的概念。它们允许程序直接访问内存地址,从而提供对数据的高效操作和灵活控制。本文将详细介绍C++中的指针定义、使用、操作以及一些注意事项。
一、指针
1、定义
指针是一个变量,其存储的是另一个变量的内存地址,而不是数据值本身。在 C++ 中,每个变量都有一个内存地址,而指针就是用来存储这些地址的变量。指针的声明通常通过在变量类型前加上星号(
*
)来完成。
int a = 10; // 定义一个整型变量 a,并赋值为 10
int *ptr = &a; // 定义一个整型指针 ptr,并将 a 的地址赋给 ptr
2、解引用
解引用是指通过指针访问它所指向的变量的值。解引用使用星号(
*
)运算符。例如:
int value = *ptr; // 通过指针 ptr 解引用,获取它所指向的变量 a 的值,并赋值给 value
3、指针的运算
指针可以进行一些基本的算术运算,如加减整数,以及比较运算。这些运算都是基于指针所指向的内存地址进行的。例如:
int arr[5] = {1, 2, 3, 4, 5};
int* p = &arr[0]; // p 指向数组的第一个元素 // 指针加法
int* q = p + 2; // q 指向数组的第三个元素(索引为 2 的元素) // 指针减法
int diff = q - p; // diff 的值为 2,因为 q 和 p 之间相隔两个元素
4、指针与数组
4.1、通过指针操作数据
在 C++ 中,数组名可以被视为指向数组第一个元素的指针。因此,数组和指针在很多情况下可以互换使用。例如:
int arr[5] = {1, 2, 3, 4, 5};
int* p = arr; // 数组名 arr 实际上是指向数组第一个元素的指针,因此可以直接赋值给指针 p
通过指针遍历数组:
for (int i = 0; i < 5; ++i) { std::cout << *(p + i) << std::endl; // 通过指针 p 遍历数组
}
4.2、指针与数组名的区别
指针与数组名区别如下:
指针 | 数组名 | |
---|---|---|
概念 | 是一个变量,存储的数据是地址 | 代表的是该数组最开始的一个元素的地址 |
sizeof | 指针变量的大小 | 计算数组占用的内存大小,通过sizeof(数组名)/sizeof(数组名[0])计算数组长度 |
常性 | 可以通过指针修改指向的变量,也可以修改保存的地址 | 数组名是一个常量,不允许修改 |
4.3、数组名作为函数形参
数组名作为函数形参时,沦为一个普通的指针,如下:
#include <iostream>using namespace std;void display(int num[], int len)
{cout << "size = " << sizeof(num) << endl;;for (int index = 0; index < len; index ++) {cout << num[index];}
}int main()
{int num[5] = {1, 2, 3, 4, 5};display(num, 5);return 0;
}
输出结果:
size = 4
12345
Process returned 0 (0x0) execution time : 0.016 s
Press any key to continue.
从输出结果可以看出来,sizeof()的结果是4,说明此时的数组名是一个普通指针。
5、指针作为函数参数
5.1、作为函数参数
通过传递指针,可以避免值传递带来的性能开销,并且可以直接修改原始数据。
void modifyValue(int* p) {*p = 20; // 修改p指向的值
}
int main() {int x = 10;modifyValue(&x); // 传递x的地址std::cout << x; // 输出20return 0;
}
5.2、常指针与指针常量
指针(
*
)与常量(const
)谁在前先读谁,例如:
int main(){int a = 10;int b = 20;int const *p1 = &a; // const在前,定义为常指针int * const p2 = &b; // *在前,定义为指针常量return 0;
}
- 常指针: 指针指向的是常量,不能通过指针改变指向的变量的值,但是指针保存的地址可以改变。
- 指针常量: 指针是常量,不能改变指针保存的地址,但是可以改变指针指向的变量。
6、指针与动态内存分配
C++ 提供了
new
和delete
运算符来进行动态内存分配和释放。与静态数组或变量不同,动态分配的内存可以在程序运行时根据需要分配和释放。例如:
int* ptr = new int; // 动态分配一个整型变量的内存
*ptr = 10; // 通过指针访问并赋值
std::cout << *ptr << std::endl; // 输出值
delete ptr; // 释放动态分配的内存
对于动态分配的数组,需要使用
delete[]
运算符来释放内存:
int* arr = new int[5]; // 动态分配一个包含 5 个整型元素的数组
for (int i = 0; i < 5; ++i) { arr[i] = i + 1;
}
for (int i = 0; i < 5; ++i) { std::cout << arr[i] << " ";
}
std::cout << std::endl;
delete[] arr; // 释放动态分配的数组内存
7、注意事项
- 空指针: 未初始化的指针可能指向任意内存地址,使用前应该将其初始化为
nullptr
(C++11 引入的)或NULL
(传统方式,但不建议在现代 C++ 中使用)。 - 野指针: 指针指向的内存已被释放,但指针本身仍然保留原来的地址。使用野指针会导致未定义行为。为了避免野指针,可以在释放内存后将指针设置为
nullptr
。 - 指针类型转换: 不同类型的指针之间不能直接转换,除非进行显式类型转换(如使用
reinterpret_cast
)。不当的指针类型转换可能导致不可预见的行为。
8、总结
指针是 C++ 编程中的一把双刃剑,它提供了对内存的直接操作能力,使得程序能够更高效地进行数据管理和访问。然而,不恰当的指针使用也可能导致严重的内存管理问题,如内存泄漏、野指针等。因此,在使用指针时,务必小心谨慎,遵循最佳实践,确保程序的稳定性和安全性。
相关文章:
C++ 编程基础(3)数据类型 | 3.1、指针
文章目录 一、指针1、定义2、解引用3、指针的运算4、指针与数组4.1、通过指针操作数据4.2、指针与数组名的区别4.3、数组名作为函数形参 5、指针作为函数参数5.1、作为函数参数5.2、常指针与指针常量 6、指针与动态内存分配7、注意事项8、总结 前言: 在C编程中&…...

nacos本地虚拟机搭建切换wiff问题
背景 在自己的电脑上搭建了vm虚拟机,安装上系统,设置网络连接。然后在vm的系统上安装了中间件nacos,mysql,redis等,后续用的中间件都是在虚拟机系统上安装的,开发在本地电脑上。 我本地启动项目总是请求到…...
打造完整 Transformer 编码器:逐步实现高效深度学习模块
11. encoder 打造完整 Transformer 编码器:逐步实现高效深度学习模块 在深入理解了编码器块的核心结构后,下一步就是实现一个完整的 Transformer 编码器。该编码器将输入序列转换为高级语义向量,并为后续的解码或其他任务模块提供高质量的特…...
软件对象粒度控制与设计模式在其中作用的例子
在软件设计中,确定对象的粒度(Granularity)是一个重要的考量因素,它决定了对象的职责范围和复杂程度。粒度过细或过粗都可能影响系统的可维护性和性能。设计模式可以帮助我们在不同层面控制粒度和管理对象之间的交互。以下是对每种…...
代码随想录算法训练营Day.3| 移除链表元素 设计链表 反转链表
长沙出差ing,今天的核心是链表,一个比较基础且重要的数据结构。对C的指针的使用,对象的创建,都比较考察,且重要。 203.移除链表元素 dummyNode虚拟头节点很重要,另外就是一个前后节点记录的问题。但是Leet…...

基于SSM的学生考勤管理系统的设计与实现
项目描述 临近学期结束,还是毕业设计,你还在做java程序网络编程,期末作业,老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。这里根据疫情当下,你想解决的问…...

制作gif动图并穿插到CSDN文章中
在我们编写文档时,需要放一些动图来增加我们文章的阅读性,在这里为大家推荐一款好用的软件LICEcap 一、下载LICEcap软件 安装包以百度网盘的形式放在了文章末尾,下载完成后,会出现下面的图标 二、如何操作 双击图标运行 会出现…...
字段值为null就不返回的注解
1. 导包 <dependency><groupId>com.fasterxml.jackson.module</groupId><artifactId>jackson-module-kotlin</artifactId> </dependency>2. 类上加注解 JsonInclude(value JsonInclude.Include.NON_NULL)3. 示例 Data JsonInclude(valu…...
spring-boot(整合aop)
第一步导入依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> 日志依赖 <dependency><groupId>org.springframework.boot</groupI…...

qt QStatusBar详解
1、概述 QStatusBar是Qt框架提供的一个小部件,用于在应用程序窗口底部显示状态信息。它可以显示一些固定的文本和图标,并且可以通过API动态更新显示内容。QStatusBar通常是一个水平的窗口部件,能够显示多行文本内容,非常适合用于…...
Docker Compose部署Powerjob
整个工具的代码都在Gitee或者Github地址内 gitee:solomon-parent: 这个项目主要是总结了工作上遇到的问题以及学习一些框架用于整合例如:rabbitMq、reids、Mqtt、S3协议的文件服务器、mongodb github:GitHub - ZeroNing/solomon-parent: 这个项目主要是…...
前端使用PDF.js把返回的base64或二进制文件流格式,实现pdf文件预览
pdf文件预览 简单了解PDF.js代码实现首先,引入依赖实现预览逻辑 简单了解PDF.js PDF.js是一个JavaScript库,可在浏览器中无插件显示PDF文件,提供缩放、翻页、文本搜索等功能。本文介绍了其基本使用方法和示例代码,如添加翻页和搜…...

如何利用 Python 的爬虫技术获取淘宝天猫商品的价格信息?
以下是使用 Python 的爬虫技术获取淘宝天猫商品价格信息的两种常见方法: 方法一:使用 Selenium 一、环境准备: 安装 selenium 库:在命令行中运行 pip install selenium。下载浏览器驱动:如 ChromeDriver(确…...

论文阅读笔记:Activating More Pixels in Image Super-Resolution Transformer
论文阅读笔记:Activating More Pixels in Image Super-Resolution Transformer 1 背景1.1 问题1.2 提出的方法 2 创新点3 方法4 模块4.1 混合注意力模块(HAB)4.2 重叠交叉注意力模块(OCAB)4.3 同任务预训练 5 效果5.1 …...
VSCode 与 HBuilderX 介绍
Visual Studio Code (VSCode) Visual Studio Code (VSCode) 是一款由 Microsoft 开发的源代码编辑器,支持多种编程语言,并且是免费和开源的。它在开发者社区中非常受欢迎,因其强大的功能和高度的可定制性而受到赞誉。 特点 轻量级且强大&am…...

《Vision Transformer with Deformable Attention》论文翻译
原文链接:https://doi.org/10.1109/cvpr52688.2022.00475 author{Zhuofan Xia and Xuran Pan and Shiji Song and Li Erran Li and Gao Huang} 一、介绍 Transformer最初是为了处理自然语言处理任务而提出的。最近,它在计算机视觉领域展示了巨大的潜力。先锋工作V…...

爬虫下载网页文夹
爬虫下载网页pdf文件 import os import requests from bs4 import BeautifulSoup from urllib.parse import urljoin from urllib.parse import urljoin, unquote from tqdm import tqdm # 设置网页的URL base_url "http://119/download/dzz/pdf/"# 创建保存文件的…...

深入探讨钉钉与金蝶云星空的数据集成技术
钉钉报销数据集成到金蝶云星空的技术案例分享 在企业日常运营中,行政报销流程的高效管理至关重要。为了实现这一目标,我们采用了轻易云数据集成平台,将钉钉的行政报销数据无缝对接到金蝶云星空的付款单系统。本次案例将重点介绍如何通过API接…...

小语言模型介绍与LLM的比较
小模型介绍 小语言模型(SLM)与大语言模型(LLM)相比,具有不同的特点和应用场景。大语言模型通常拥有大量的参数(如 GPT-3 拥有 1750 亿个参数),能够处理复杂的自然语言任务ÿ…...
ThreadLocal从入门到精通
1.ThreadLocal是什么 ThreadLocal 是 Java 提供的一个用于线程存储本地变量的类。它为每个线程提供独立的变量副本,确保变量在多线程环境下的线程安全。每个线程访问 ThreadLocal 时,都会有自己专属的变量副本,互不干扰,避免了并…...
【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密
在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...
JVM垃圾回收机制全解析
Java虚拟机(JVM)中的垃圾收集器(Garbage Collector,简称GC)是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象,从而释放内存空间,避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...

select、poll、epoll 与 Reactor 模式
在高并发网络编程领域,高效处理大量连接和 I/O 事件是系统性能的关键。select、poll、epoll 作为 I/O 多路复用技术的代表,以及基于它们实现的 Reactor 模式,为开发者提供了强大的工具。本文将深入探讨这些技术的底层原理、优缺点。 一、I…...

C++ Visual Studio 2017厂商给的源码没有.sln文件 易兆微芯片下载工具加开机动画下载。
1.先用Visual Studio 2017打开Yichip YC31xx loader.vcxproj,再用Visual Studio 2022打开。再保侟就有.sln文件了。 易兆微芯片下载工具加开机动画下载 ExtraDownloadFile1Info.\logo.bin|0|0|10D2000|0 MFC应用兼容CMD 在BOOL CYichipYC31xxloaderDlg::OnIni…...

让回归模型不再被异常值“带跑偏“,MSE和Cauchy损失函数在噪声数据环境下的实战对比
在机器学习的回归分析中,损失函数的选择对模型性能具有决定性影响。均方误差(MSE)作为经典的损失函数,在处理干净数据时表现优异,但在面对包含异常值的噪声数据时,其对大误差的二次惩罚机制往往导致模型参数…...

C/C++ 中附加包含目录、附加库目录与附加依赖项详解
在 C/C 编程的编译和链接过程中,附加包含目录、附加库目录和附加依赖项是三个至关重要的设置,它们相互配合,确保程序能够正确引用外部资源并顺利构建。虽然在学习过程中,这些概念容易让人混淆,但深入理解它们的作用和联…...
4. TypeScript 类型推断与类型组合
一、类型推断 (一) 什么是类型推断 TypeScript 的类型推断会根据变量、函数返回值、对象和数组的赋值和使用方式,自动确定它们的类型。 这一特性减少了显式类型注解的需要,在保持类型安全的同时简化了代码。通过分析上下文和初始值,TypeSc…...

基于Java+VUE+MariaDB实现(Web)仿小米商城
仿小米商城 环境安装 nodejs maven JDK11 运行 mvn clean install -DskipTestscd adminmvn spring-boot:runcd ../webmvn spring-boot:runcd ../xiaomi-store-admin-vuenpm installnpm run servecd ../xiaomi-store-vuenpm installnpm run serve 注意:运行前…...
【实施指南】Android客户端HTTPS双向认证实施指南
🔐 一、所需准备材料 证书文件(6类核心文件) 类型 格式 作用 Android端要求 CA根证书 .crt/.pem 验证服务器/客户端证书合法性 需预置到Android信任库 服务器证书 .crt 服务器身份证明 客户端需持有以验证服务器 客户端证书 .crt 客户端身份…...

算法—栈系列
一:删除字符串中的所有相邻重复项 class Solution { public:string removeDuplicates(string s) {stack<char> st;for(int i 0; i < s.size(); i){char target s[i];if(!st.empty() && target st.top())st.pop();elsest.push(s[i]);}string ret…...