C++学习路程-5-入门-指针

1. 什么是指针?

指针是一个变量,其值是另一个变量的内存地址。通过指针,可以直接访问和操作内存,这为动态内存分配、数组处理和函数参数传递等提供了强大的灵活性。指针在C++中是非常重要的概念,但由于其直接操作内存的特性,使用不当可能导致程序崩溃或内存泄漏。

2. 指针的定义与初始化

2.1 定义指针

指针的定义格式为类型 *指针名,其中类型表示指针所指向的数据类型。指针的类型决定了它所指向数据的大小和如何解释内存中的数据。

示例:

cpp

int* ptr; // 定义一个指向整数的指针

在这个例子中,ptr是一个指针变量,能够存储一个整数类型的地址。

2.2 初始化指针

指针可以通过一个变量的地址进行初始化。使用&运算符可以获取变量的地址。

示例:

cpp

int value = 10;
int* ptr = &value; // ptr现在指向value的地址

在这个例子中,ptr被初始化为value的地址。要注意,未初始化的指针会指向一个随机地址,可能导致未定义行为。

3. 访问指针所指向的值

可以使用解引用运算符(*)来访问指针所指向的值。解引用是指通过指针访问其指向的内存位置。

示例:

cpp

#include <iostream>
using namespace std;

int main() {
    int value = 10;
    int* ptr = &value; // ptr指向value的地址
    cout << "Value: " << *ptr << endl; // 通过指针访问值,输出10
    *ptr = 20; // 修改指针所指向的值
    cout << "New Value: " << value << endl; // 输出20
    return 0;
}

在上述例子中,*ptr解引用ptr以获取value的值,并且可以通过*ptr修改value的值。

4. 指针的类型

指针的类型与其所指向的数据类型相匹配,指针的类型决定了指针的大小和解引用的方式。常见的指针类型包括:

  • 整型指针int*,指向整数类型。
  • 字符指针char*,指向字符类型,常用于字符串。
  • 浮点型指针float*,指向浮点类型。
  • 双浮点型指针double*,指向双精度浮点类型。
  • void指针void*,可以指向任何类型,但不能直接解引用,通常用于通用指针。

5. 指针的数组与字符串

5.1 指针与数组

数组名在大多数情况下可以被视为指向数组首元素的指针。数组和指针之间的关系使得可以通过指针访问数组元素。

示例:

cpp

#include <iostream>
using namespace std;

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

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

在这个例子中,ptr指向数组arr的首元素,*(ptr + i)通过指针算术访问数组的每个元素。

5.2 指针与字符串

C风格字符串是以空字符('\0')结尾的字符数组,可以通过字符指针访问。

示例:

cpp

#include <iostream>
using namespace std;

int main() {
    char str[] = "Hello";
    char* ptr = str; // 指向字符串的首字符

    while (*ptr != '\0') { // 遍历字符串直到遇到空字符
        cout << *ptr; // 输出字符
        ptr++;
    }
    cout << endl;
    return 0;
}

在这个例子中,ptr指向字符串的首字符,通过解引用和指针递增遍历字符串。

6. 动态内存分配

C++提供了newdelete运算符用于动态内存分配和释放。动态内存分配允许程序在运行时请求内存,这在处理不确定大小的数据结构时非常有用。

6.1 使用new分配内存

使用new运算符为指针分配内存。new会返回指向所分配内存的指针。

示例:

cpp

int* ptr = new int; // 动态分配一个整数
*ptr = 10; // 赋值
cout << *ptr << endl; // 输出10
6.2 使用delete释放内存

使用delete运算符释放动态分配的内存,以避免内存泄漏。每次使用new分配的内存都应该在不再需要时用delete释放。

示例:

cpp

delete ptr; // 释放内存
ptr = nullptr; // 设置指针为nullptr,避免悬空指针

7. 指针的常见错误

  • 野指针:指向未分配或已释放内存的指针,使用时可能导致未定义行为。确保指针在使用前被初始化,并在释放后将其设置为nullptr

  • 内存泄漏:未释放动态分配的内存,导致程序占用的内存不断增加。确保每次new分配的内存都有对应的delete释放。

  • 指针算术错误:不当使用指针算术可能导致越界访问,特别是在处理数组时。

8. 指针与函数

8.1 传递指针给函数

可以将指针作为参数传递给函数,这样可以在函数内部修改原始变量的值。这种方式称为通过引用传递。

示例:

cpp

void increment(int* num) {
    (*num)++; // 修改原始变量
}

int main() {
    int value = 10;
    increment(&value); // 传递变量的地址
    cout << value; // 输出11
    return 0;
}

在这个例子中,increment函数接收一个指向整数的指针,通过解引用修改了value的值。

8.2 函数返回指针

函数可以返回指向动态分配内存的指针,但需要小心管理内存,以避免返回指向已释放内存的指针。

示例:

cpp

int* createArray(int size) {
    return new int[size]; // 动态分配数组
}

int main() {
    int* arr = createArray(5);
    for (int i = 0; i < 5; i++) {
        arr[i] = i + 1;
    }

    for (int i = 0; i < 5; i++) {
        cout << arr[i] << " "; // 输出数组元素
    }
    delete[] arr; // 释放数组内存
    return 0;
}

在这个例子中,createArray函数返回一个指向动态数组的指针。在主函数中,使用delete[]释放动态分配的数组内存。

9. 指针的指针

指针的指针是指向指针的指针,可以用于多级指针。指针的指针可以用于动态数组或复杂数据结构的管理。

示例:

cpp

int value = 10;
int* ptr = &value; // 指向整数的指针
int** ptrToPtr = &ptr; // 指向指针的指针

cout << **ptrToPtr << endl; // 输出10

在这个例子中,ptrToPtr是一个指向ptr的指针,通过解引用可以访问value的值。

10. 常用指针运算

  • 解引用:使用*运算符访问指针所指向的值。

  • 指针算术:指针可以进行加法和减法运算,例如通过ptr + 1访问下一个元素的地址。指针算术会根据元素类型自动调整地址。

11. 智能指针

C++11引入了智能指针(如std::unique_ptrstd::shared_ptr),用于自动管理动态内存,减少内存泄漏的风险。

11.1 std::unique_ptr

std::unique_ptr是独占所有权的智能指针,确保同一时间内只有一个指针指向某个对象。

cpp

#include <iostream>
#include <memory>
using namespace std;

int main() {
    unique_ptr<int> ptr(new int(10)); // 创建智能指针
    cout << *ptr << endl; // 输出10
    // 不需要手动释放内存,ptr离开作用域时自动释放
    return 0;
}
11.2 std::shared_ptr

std::shared_ptr可以多个指针共享同一个对象,使用引用计数来管理内存。当最后一个指向该对象的shared_ptr被销毁时,内存才会被释放。

cpp

#include <iostream>
#include <memory>
using namespace std;

int main() {
    shared_ptr<int> ptr1(new int(10));
    shared_ptr<int> ptr2 = ptr1; // ptr2共享ptr1的所有权
    cout << *ptr1 << " " << *ptr2 << endl; // 输出10
    return 0; // 自动释放内存
}

12. 总结

指针是C++中非常强大和灵活的特性。它们允许直接操作内存,可以方便地实现动态内存管理、数组和字符串处理、以及函数参数传递等功能。然而,指针的使用需要小心,以避免常见的问题,如内存泄漏、野指针和悬空指针。

常见问题及最佳实践

  1. 避免使用未初始化的指针:确保指针在使用前被初始化,以避免野指针。

  2. 及时释放动态内存:使用delete或智能指针确保内存被正确释放,避免内存泄漏。

  3. 使用智能指针:尽可能使用智能指针来管理动态内存,减少手动管理带来的复杂性。

  4. 检查指针有效性:在解引用指针之前,确保指针不为nullptr

  5. 注意指针算术:在进行指针算术时,确保不会越界。

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

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

相关文章

帝国CMS自动生成标题图片并写进数据库

帝国CMS背景可自定义&#xff0c;可单独背景也可以随机背景,此插件根帝国cms官方论坛帖子改的&#xff0c;增加了生成图片后写入数据库,笔者的古诗词网 www.gushichi.com 也是这样设置的。 效果图 将下面的代码插入到/e/class/userfun.php中增加如下函数 单独背景代码 //自动…

数据分析和AI丨知识图谱,AI革命中数据集成和模型构建的关键推动者

人工智能&#xff08;AI&#xff09;已经吸引了数据科学家、技术领导者以及任何使用数据进行商业决策者的兴趣。绝大多数企业都希望利用人工智能技术来增强洞察力和生产力&#xff0c;而对于这些企业而言&#xff0c;数据集的质量差成为了最主要的障碍。 数据源需要进行清洗且明…

java小知识点:比较器

java中自主排序主要根据一个Comparator类来实现。 他内部实现用的是Timsort策略。大概思想是说将整个集合分成几个小段&#xff0c;每个小段分别排序&#xff0c;然后再拼在一起。 主要用法是传入两个数&#xff08;也可以不是Integer或int类型&#xff0c;这里只是把他们都统称…

【嵌入式开发笔记】OpenOCD到嵌入式调试

最近在把玩一块Risc-V的开发板&#xff0c;使用开发板调试时&#xff0c;需要用到专门的下载器和OpenOCD进行调试。 为了连接这个板子&#xff0c;费了九牛二虎之力。 这里简单记录一下自己的折腾经过吧。 0x00 环境准备 0x0001 调试背景 系统&#xff1a;Virtual Box Ub…

安装MongoDB,环境配置

官网下载地址&#xff1a;MongoDB Shell Download | MongoDB 选择版本 安装 下载完成双击打开 点击mongodb-windows-x86_64-8.0.0-signed 选择安装地址 检查安装地址 安装成功 二.配置MongoDB数据库环境 1.找到安装好MongoDB的bin路径 复制bin路径 打开此电脑 -> 打开高级…

15.初识接口1 C#

这是一个用于实验接口的代码 适合初认识接口的人 【CSDN开头介绍】&#xff08;文心一言AI生成&#xff09; 在C#编程世界中&#xff0c;接口&#xff08;Interface&#xff09;扮演着至关重要的角色&#xff0c;它定义了一组方法&#xff0c;但不提供这些方法的实现。它要求所…

2.学习TypeScript 编译选项配置

自动编译 我们可以使用 tsc ...../.ts -w 命令进行ts文件的自动编译 执行后 编译会持续侦听 自动编译 这种方式只能侦听一个文件 对做项目肯定是不现实的&#xff0c;为了解决这个问题&#xff0c;我们需要添加一个tsconfig.json文件&#xff0c;写入一个基础对象 再有tsconfi…

Python爬虫(5) --爬取网页视频

文章目录 爬虫爬取视频指定url发送请求UA伪装请求页面 获取想要的数据解析定位定位音视频位置 存放视频完整代码实现总结 爬虫 Python 爬虫是一种自动化工具&#xff0c;用于从互联网上抓取网页数据并提取有用的信息。Python 因其简洁的语法和丰富的库支持&#xff08;如 requ…

VS Code Copilot 与 Cursor 对比

选手简介 VS Code Copilot&#xff1a;算是“老牌”编程助手了&#xff0c;虽然Copilot在别的编辑器上也有扩展&#xff0c;不过体验最好的还是VS Code&#xff0c;毕竟都是微软家的所以功能集成更好一些&#xff1b;主要提供的是Complete和Chat能力&#xff0c;也就是代码补全…

基础元器件的学习

1、二极管 1.1二极管的符号 ZD是稳压二极管 VD、V、D是普通二极管的符号。 1.2二极管的反向恢复时间 首先交流电为上正下负&#xff0c;然后下正上负。当二极管接到反向电压&#xff0c;二极管存在寄生电容&#xff0c;电压不能立刻突变&#xff0c;当输入频率变高时&#…

unipp中使用阿里图标,以及闭坑指南

-----------------------------------------------------点赞收藏才是更新的动力------------------------------------------------- unipp中使用阿里图标 官网下载图标在项目中引入使用注意事项 官网下载图标 进入阿里图标网站 将需要下载的图标添加到购物车中 2. 直接下载…

QtCreator配置github copilot实现AI辅助编程

文章目录 1、概述2、配置环境3、演示 1、概述 新时代的浪潮早就已经来临&#xff0c;上不了船的人终将被抛弃&#xff0c;合理使用AI辅助开发、提升效率是大趋势&#xff0c;注意也不要过于依赖。 2024年12月18日&#xff0c;GitHub 官方宣布了一个激动人心的重大消息&#xf…

web实操8-cookie

会话技术 会话&#xff1a; 一次会话中包含多次请求和响应。 客户端浏览器访问服务器的资源&#xff0c;只要客户端或者服务器端不关闭&#xff0c;这始终在一次会话范围内&#xff0c;这一次会话范围内可以包含多次请求并且收到多次相应。 一次会话&#xff1a;浏览器第一…

深度学习之超分辨率算法——SRCNN

网络为基础卷积层 tensorflow 1.14 scipy 1.2.1 numpy 1.16 大概意思就是针对数据&#xff0c;我们先把图片按缩小因子照整数倍进行缩减为小图片&#xff0c;再针对小图片进行插值算法&#xff0c;获得还原后的低分辨率的图片作为标签。 main.py 配置文件 from model im…

Javaweb 在线考试系统

&#x1f942;(❁◡❁)您的点赞&#x1f44d;➕评论&#x1f4dd;➕收藏⭐是作者创作的最大动力&#x1f91e; &#x1f496;&#x1f4d5;&#x1f389;&#x1f525; 支持我&#xff1a;点赞&#x1f44d;收藏⭐️留言&#x1f4dd;欢迎留言讨论 &#x1f525;&#x1f525;&…

Qt for Python (PySide6)设置程序图标和任务栏图标

环境 使用Qt for Python开发Windows应用程序。 Python版本&#xff1a;3.12 Qt版本&#xff1a;PySide6 前言 先上一个简单的测试程序 from PySide6.QtWidgets import QMainWindow,QLabel,QApplication from PySide6 import QtGui import sysclass MainWindow(QMainWindow)…

【C#】实现Json转Lua (Json2Lua)

关键词: C#、JsonToLua、Json2Lua、对象序列化Lua 前提需引入NewtonsofJson&#xff0c;引入方法可先在Visual Studio 2019 将Newtonsoft.Json.dll文件导入Unity的Plugins下。 Json格式字符串转Lua格式字符串&#xff0c;效果如下&#xff1a; json字符串 {"1": &q…

Windows平台C++部署 vcpkg 安装protobuf + gRPC实现图像传输

vcpkg 安装 https://github.com/microsoft/vcpkg.git.\bootstrap-vcpkg.bat vcpkg --version参考&#xff1a;Windows安装vcpkg教程&#xff08;VS2022&#xff09; protocbuf 安装与编译 vcpkg install grpc:x64-windowsprotocbuf 安装与编译 vcpkg install protobuf proto…

ScottPlot学习的常用笔记-02

ScottPlot学习的常用笔记-02 写在前面Why&Target&#xff1a;这里记一些杂项。上下文&背景 先记一下这几个小时的新收获先说一下&#xff0c;为什么可开发可视工具缩放的问题ScottPlot5.0起步.net Core: WinExe.Net Framework也是可以的 写在前面 Why&Target&…

CTF_1

CTF_Show 萌新赛 1.签到题 <?php if(isset($_GET[url])){system("curl https://".$_GET[url].".ctf.show"); }else{show_source(__FILE__); }?> 和 AI 一起分析 1.if(isset($_GET[url]))检查GET请求中是否存在名为url的参数。 curl 2.curl…