C++基础精讲-02

文章目录

  • 1.C/C++申请、释放堆空间的方式对比
    • 1.1C语言申请、释放堆空间
    • 1.2C++申请、释放堆空间
      • 1.2.1 new表达式申请数组空间
    • 1.3回收空间时的注意事项
    • 1.4malloc/free 和 new/delete 的区别
  • 2.引用
    • 2.1 引用的概念
    • 2.2 引用的本质
    • 2.3 引用与指针的联系与区别
    • 2.4 引用的使用场景
      • 2.4.1 引用作为函数的参数
    • 2.5 引用作为函数的返回值
    • 2.6 总结
  • 3.强制类型转换
    • 3.1 c语言里的强制类型转换
    • 3.2 c++数据类型强制转换
      • 3.2.1 static_cast(常用)
      • 3.2.3 const_cast (常不用)
      • 3.2.3 其他(后面章节中应用到在讲解)


1.C/C++申请、释放堆空间的方式对比

1.1C语言申请、释放堆空间

关于C语言的堆内存管理内存管理不熟悉可看以下章节
C语言精讲-12
c语言中申请、释放堆空间一般用malloc和free函数

#include<stdio.h>
#include<stdlib.h>void test(void)
{//申请内存int*p=(int*) malloc(sizeof(int));if(NULL==p){printf("内存申请失败\n");exit(0) ;}*p=10;printf("*p=%d\n",*p);//释放内存;free(p);p=NULL;}int main(void)
{test();return 0;}

在这里插入图片描述

1.2C++申请、释放堆空间

c++申请、释放堆空间一般用new/delete表达式;

#include<iostream>
using std::cout;
using std::endl;void test(void)
{//初始化为该类型的默认值int * p1 = new int();cout<<*p1<<endl;int *p2=new int(2);cout<<*p2<<endl;//释放内存delete p1;delete p2;//将 p1 和 p2 置为 nullptr;避免野指针p1= nullptr;p2= nullptr;}int main(void)
{test();return 0;}

1.2.1 new表达式申请数组空间

1.默认初始化为0;

#include<iostream>
using std::cout;
using std::cin;
using std::endl;void test(void)
{//将动态分配的数组元素默认初始化为 0//申请10个int类型的堆空间int * p1 = new int[10]();for(int idx = 0; idx < 10; ++idx){p1[idx] = idx;}for(int idx = 0; idx < 10; ++idx){cout << p1[idx] << endl;}//释放堆空间delete [] p1;p1=nullptr;}int main(void)
{       test();return 0;
}       
~                                       

在这里插入图片描述
2.赋初值

#include<iostream>
using std::cout;
using std::cin;
using std::endl;void test(void)
{       //申请3个int类型的堆空间int * p1 = new int[3]{2,4,6};for(int i=0;i<3;i++){cout<<p1[i]<<endl;}//释放堆空间delete [] p1;p1=nullptr;}int main(void)
{       test();return 0;
}       
~                           

在这里插入图片描述

1.3回收空间时的注意事项

1.三组申请空间和回收空间的匹配组合

malloc            freenew               deletenew int[5]()      delete[]

2安全回收
delete只是回收了指针指向的空间,但这个指针变量依然还在,指向了不确定的内容(野指针),容易造成错误。所以需要进行安全回收,将这个指针设为空指针C++11之后使用nullptr表示空指针。

1.4malloc/free 和 new/delete 的区别

1.malloc/free 是库函数;new/delete 是表达式,后两者使用时不是函数的写法;
2.new 表达式的返回值是相应类型的指针,malloc 返回值是 void*;
3.malloc 申请的空间不会进行初始化,获取到的空间是有脏数据的,但 new 表达式申请空间时可以直接初始化;
4.malloc 的参数是字节数,new 表达式不需要传递字节数,会根据相应类型自动获取空间大小。

2.引用

2.1 引用的概念

引用是c++对c的重要扩充。在c/c++中指针的作用基本都是一样的,但是c++增加了另外一种给函数传递地址的途径,这就是按引用传递
变量概述
1.变量名实质上是一段连续内存空间的别名,是一个标号(门牌号)
2.程序中通过变量来申请并命名内存空间
3.通过变量的名字可以使用存储空间
c++中新增了引用的概念,引用可以作为一个已定义变量的别名。
基本语法:

Type& ref = val;
示例:
int number = 2;
int & ref = number;
#include<iostream>
using std::cout;
using std::cin;
using std::endl;int main(void)
{int sum=10;cout<<"sum="<<sum<<endl;int&s=sum;cout<<"s="<<s<<endl;s=100;cout<<"s="<<s<<endl<<"num="<<sum<<endl;return 0;
}

在这里插入图片描述
注意事项
&在此不是求地址运算,而是起标识作用。
类型标识符是指目标变量的类型
必须在声明引用变量时进行初始化。
引用初始化之后不能改变
不能有NULL引用。必须确保引用是和一块合法的存储单元关联。

2.2 引用的本质

引用的本质在c++内部实现是一个常指针;c++编译器在编译过程中使用常指针作为引用的内部实现,因此引用所占用的空间大小与指针相同,只是这个过程是编译器内部实现,用户不可见。

#include<iostream>
using std::cout;
using std::cin;
using std::endl;void test(void)
{int sum=10;int &s=sum;int*p=&sum;cout<<"sum的地址:"<<&sum<<endl;cout<<"s的地址:"<<&s<<endl;cout<<"p所指向的地址:"<<p<<endl;cout<<"size(p)="<<sizeof(p)<<endl;//指针p占多少字节cout<<"size(s)="<<sizeof(&s)<<endl;//引用&s占多数字节
}int main(void)
{test();return 0;
}

在这里插入图片描述

2.3 引用与指针的联系与区别

联系:

  1. 引用和指针都有地址的概念,都是用来间接访问变量;

  2. 引用的底层还是指针来完成,可以把引用视为一个常指针。

区别
4. 引用必须初始化,指针可以不初始化;
5. 引用不能修改绑定,但是指针可以修改指向;
6. 在代码层面对引用本身取址取到的是变量本体的地址,但是对指针取址取到的是指针变量的地址

2.4 引用的使用场景

2.4.1 引用作为函数的参数

在没有引用之前,如果我们想通过形参改变实参的值,只有使用指针才能到达目的。但使用指针的过程中,不好操作,很容易犯错。 而引用既然可以作为其他变量的别人而存在,那在很多场合下就可以用引用代替指针,因而也具有更好的可读性和实用性。这就是引用存在的意义。

#include<iostream>
using std::cout;
using std::cin;
using std::endl;//使用指针
void swap(int *a,int*b)
{int temp=*a;*a=*b;*b=temp;
}
//使用引用
void swap2(int&a,int&b)
{int temp=a;a=b;b=temp;
}void test1(void)
{int a=10,b=20;cout<<"交换前:a="<<a<<",b="<<b<<endl;swap(&a,&b);cout<<"交换后:a="<<a<<",b="<<b<<endl;swap2(a,b);cout<<"再次交换后:a="<<a<<"b="<<b<<endl;
}
int main(void)
{test1();return 0;
}

在这里插入图片描述

2.5 引用作为函数的返回值

当以引用作为函数的返回值时,返回的变量其生命周期一定是要大于函数的生命周期的,即当函数执行完毕时,返回的变量还存在。
目的: 避免复制,节省开销

#include<iostream>
using std::cout;
using std::cin;
using std::endl;int fun1(void)
{int a=10;//返回的是a的副本,变量a是局部变量。在fun1函数结束时a的空间就被回收cout<<"fun a的地址:"<<&a<<endl;return a;
}int& fun2(void)
{///使用指针/引用作为返回值时候,不可返回一个局部的变量;可加static修饰static int  b=100;//返回的是一个绑定b的的引用;cout<<"fun2 b的地址:"<<&b<<endl;return b;
}int main(void)
{//把fun1中a的值复制给main函数中的变量a;int a=fun1();cout<<"main中a的地址:"<<&a<<endl;int &b=fun2();cout<<"main 中引用b的地址:"<<&b<<endl;return 0;
}

在这里插入图片描述
注意事项
1.不要返回局部变量的引用。因为局部变量会在函数返回后被销毁,被返回的引用就成为了"无所指"的引用,程序会进入未知状态。
2.不要轻易返回一个堆空间变量的引用,非常容易造成内存泄漏。

int & func()
{int * pint = new int(1);return *pint;
}void test()
{int a = 2, b = 4;int c = a + func() + b;//内存泄漏
}

2.6 总结

  1. 在引用的使用中,单纯给某个变量取个别名没有什么意义,引用的目的主要用于在函数参数传递中,解决大块数据或对象的传递效率和空间不理想的问题。
  2. 用引用传递函数的参数,能保证参数传递中不产生副本,提高传递的效率,还可以通过const的使用,保证了引用传递的安全性。
  3. 引用与指针的区别是,指针通过某个指针变量指向一个变量后,对它所指向的变量间接操作。程序中使用指针,程序的可读性差;引用底层仍然是指针,但是编译器不允许访问到这个底层的指针,逻辑上简单理解为——对引用的操作就是对目标变量的操作。可以用指针或引用解决的问题,更推荐使用引用

3.强制类型转换

3.1 c语言里的强制类型转换

格式:数据类型 变量1 = (数据类型)变量2;

#include<stdio.h>int main(void)
{       float a=3.14f;printf("a=%f\n",a);int b=(int)a;printf("b=%d\n",b);return 0;
}       

缺点:

  1. 数据丢失风险高
    C 语言的强制类型转换语法简单,不过在将大类型转换为小类型时,容易发生数据丢失。比如把long类型转换为int类型,若long类型的值超出int类型的范围,就会出现数据截断。
  2. 破坏类型系统且缺乏安全性检查
    C 语言允许进行各种类型的强制转换,像指针类型的转换,这可能会破坏类型系统的安全性,编译器也不会做严格的类型检查。例如将void*指针转换为其他类型的指针,若使用不当,就会引发未定义行为。
  3. 掩盖潜在错误
    C 语言的强制类型转换可能会掩盖代码中的潜在错误,使代码能通过编译,但实际上逻辑可能存在问题。
  4. 可移植性差
    不同平台上数据类型的大小和表示方式可能不同,C 语言的强制类型转换可能会导致在不同平台上产生不同的结果,影响代码的可移植性。

3.2 c++数据类型强制转换

3.2.1 static_cast(常用)

最常用的类型转换符,在正常状况下的类型转换, 用于将一种数据类型转换成另一种数据类型,如把int转换为float

目标类型 转换后的变量 = static_cast<目标类型>(要转换的变量)

好处:不允许非法的转换发生;方便查找

int a = 100float f = 0;
f = (float) a;//C风格
f = static_cast<float>(a);
void * p1 = malloc(sizeof(int));
int * p2 = static_cast<int*>(p1);
*p2 = 1;

不能完成任意两个指针类型间的转换(限制一些非法转换)

int a = 1;
int * p1 = &a;
float * p2 = static_cast<float *>(p1);//错误

总结,static_cast的用法主要有以下几种:

1)用于基本数据类型之间的转换,如把int转换成char,把int转换成enum。这种转换的安全性需要开发人员来保证;
2)把void指针转换成目标类型的指针,但不安全;
3)把任何类型的表达式转换成void类型;
4)用于类层次结构中基类和子类之间指针或引用的转换

3.2.3 const_cast (常不用)

该运算符用来修改类型的const属性。
指向常量的指针被转化成普通指针,并且仍然指向原来的对象;
常量引用被转换成非常量引用,并且仍然指向原来的对象;

const int number = 100;
int * pInt = &number;//error
int * pInt2 = const_cast<int *>(&number);

3.2.3 其他(后面章节中应用到在讲解)

dynamic_cast:该运算符主要用于基类和派生类间的转换;
reinterpret_cast:功能强大,慎用(也称为万能转换);

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

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

相关文章

Spring Boot MongoDB 分页工具类封装 (新手指南)

Spring Boot MongoDB 分页工具类封装 (新手指南) 目录 引言&#xff1a;为何需要分页工具类&#xff1f;工具类一&#xff1a;PaginationUtils - 简化 Pageable 创建 设计目标代码实现 (PaginationUtils.java)如何使用 PaginationUtils 工具类二&#xff1a;PageResponse<…

MyBatis的缓存、逆向工程、使用PageHelper、使用PageHelper

一、MyBatis的缓存 缓存&#xff1a;cache 缓存的作用&#xff1a;通过减少IO的方式&#xff0c;来提高程序的执行效率。 mybatis的缓存&#xff1a;将select语句的查询结果放到缓存&#xff08;内存&#xff09;当中&#xff0c;下一次还是这条select语句的话&#xff0c;直…

java中的JNI调用c库

1. 简单demo 如果是在某个项目中有包名就需要自己找ai问问去改写下cmd命令去编译执行等 java文件&#xff08;HelloJNI.java&#xff09; public class HelloJNI {// 声明 native 方法public native void sayHello();// 加载本地库static {System.loadLibrary("hello&quo…

人工智能:GPT技术应用与未来展望

GPT(Generative Pre-trained Transformer)作为自然语言处理领域的代表性技术,近年来在各行业的实际应用中展现出广泛潜力。结合其技术特性与行业需求,以下是GPT的主要应用场景、案例分析及未来挑战的总结: 一、核心应用领域与案例 文本生成与内容创作 自动化内容生产:GPT…

前端笔记-ECMAScript语法概览

更多详细可以查看1.1 ES6 教程 | 菜鸟教程 这里我将大概记录ES与JS大概不一样的部分&#xff0c;方便联合记忆。 历史与关系 ECMAScript&#xff1a;是一种由 Ecma 国际组织制定的脚本语言规范&#xff0c;它是 JavaScript 的标准化版本。ECMAScript 为 JavaScript 提供了语…

操作主机的管理

1.在AD林范围内&#xff0c;有哪几个操作主机角色 架构主机&#xff08;Schema Master&#xff09; 功能&#xff1a;负责整个AD林中所有对象和属性的定义&#xff0c;是唯一可以更新目录架构的DC。架构更新会从架构主机复制到目录林中的所有其他域控制器。 作用范围&#xf…

【Linux】网络编程

目录 端口号 网络字节序 socket编程 接口 sockaddr结构 udp网络程序 创建套接字 绑定 接收 发送 客户端需要绑定吗&#xff1f; 客户端执行方法 本地环回地址 终端文件 代码 tcp网络程序 SOCK_STREAM 监听 查询网络信息 获取新连接 地址转换函数 客户端绑…

Go 语言中的select是做什么的

Go 语言中的 select 是做什么的 在 Go 语言中&#xff0c;select 语句是用于处理多个通道&#xff08;channel&#xff09;操作的一种控制结构。它类似于 switch 语句&#xff0c;但专门用于并发编程&#xff0c;允许 Goroutine 在多个通道上等待操作&#xff08;发送或接收&a…

智慧班牌系统解决方案,SaaS智慧电子班牌云平台

智慧班牌系统解决方案 系统概述 智慧班牌是智慧校园建设不断发展的产物&#xff0c;是教育信息化改革的载体。通过智慧班牌可以高效便捷传递各种知识信息和通知信息、及时反馈课堂信息、实现班级的透明化管理。智慧班牌将学生平安考勤、异常出勤情况及时反馈至家长、老师&…

利用大模型和聚类算法找出 Excel 文件中重复或相似度高的数据,并使用 FastAPI 进行封装的详细方案

以下是一个利用大模型和聚类算法找出 Excel 文件中重复或相似度高的数据,并使用 FastAPI 进行封装的详细方案: 方案流程 数据读取:从 Excel 文件中读取数据。文本向量化:使用大模型将文本数据转换为向量表示。聚类分析:运用聚类算法对向量进行分组,将相似度高的数据归为…

【Docker基础】容器技术详解:生命周期、命令与实战案例

文章目录 一、什么是容器&#xff1f;二、为什么需要容器三、容器的生命周期容器状态容器OOM容器异常退出容器异常退出容器暂停 四、容器命令命令清单详细介绍 五、容器操作案例容器的状态迁移容器批量操作容器交互模式attached 模式detached 模式interactive 模式 容器 与 宿主…

Laravel 实现 队列 发送邮件功能

一. 什么是队列 在构建 Web 应用程序时&#xff0c;你可能需要执行一些任务&#xff0c;例如解析文件&#xff0c;发送邮件&#xff0c;大量的数据计算等等&#xff0c;这些任务在典型的 Web 请求期间需要很长时间才能执行。 庆幸的是&#xff0c;Laravel 可以创建在后台运行…

flink Shuffle的总结

关于 ** ​5 种 Shuffle 类型** 的区别、使用场景及 Flink 版本支持的总结&#xff1a; * 注意:下面是问AI具体细节与整理学习 1. 核心区别 Shuffle 类型核心特点使用场景Flink 版本支持Pipelined Shuffle流式调度&#xff0c;纯内存交换&#xff0c;低延迟&#xff08;毫秒级…

Git使用与管理

一.基本操作 1.创建本地仓库 在对应文件目录下进行&#xff1a; git init 输入完上面的代码&#xff0c;所在文件目录下就会多一个名为 .git 的隐藏文件&#xff0c;该文件是Git用来跟踪和管理仓库的。 我们可以使用 tree 命令&#xff08;注意要先下载tree插件&#xff09…

计算机视觉——深度学习图像处理中目标检测平均精度均值(mAP)与其他常用评估指标

概述 平均精度均值&#xff08;mAP&#xff09;是目标检测领域中最为流行且复杂的重要评估指标之一。它广泛用于综合总结目标检测器的性能。许多目标检测模型会输出类似以下的参数结果&#xff1a; Average Precision (AP) [ IoU0.50:0.95 | area all | maxDets100 ] 0.3…

C语言中单链表操作:查找节点与删除节点

一. 简介 前面学习了C语言中创建链表节点&#xff0c;向链表中插入节点等操作&#xff0c;文章如下&#xff1a; C语言中单向链表&#xff1a;创建节点与插入新节点-CSDN博客 本文继续学习c语言中对链表的其他操作&#xff0c;例如在链表中查找某个节点&#xff0c;删除链表…

WePY 框架:小程序开发的“Vue式”利器!!!

WePY 框架&#xff1a;小程序开发的“Vue式”利器 &#x1f680; 哈喽&#xff0c;大家好&#xff01;&#x1f44b; 今天我们要聊聊一个在微信小程序开发中大放异彩的框架——WePY&#xff01;它是什么&#xff1f;有什么特点&#xff1f;为啥值得一试&#xff1f;别急&#…

什么是微前端?有什么好处?有哪一些方案?

微前端&#xff08;Micro Frontends&#xff09; 微前端是一种架构理念&#xff0c;借鉴了微服务的思想&#xff0c;将一个大型的前端应用拆分为多个独立、自治的子应用&#xff0c;每个子应用可以由不同团队、使用不同技术栈独立开发和部署&#xff0c;最终聚合为一个整体产品…

【家政平台开发(33)】库存管理模块开发实战:从基础搭建到智能管控

本【家政平台开发】专栏聚焦家政平台从 0 到 1 的全流程打造。从前期需求分析,剖析家政行业现状、挖掘用户需求与梳理功能要点,到系统设计阶段的架构选型、数据库构建,再到开发阶段各模块逐一实现。涵盖移动与 PC 端设计、接口开发及性能优化,测试阶段多维度保障平台质量,…

Mysql个人笔记

Mysql个人笔记 sql基础书写规则和种类种类书写规则注释规则启动 DDL数据类型数据库的操作useshowcreatedrop 表的操作useshowcreate创建表复制表 dropalter Mysql的存储引擎 DMLselectselect语句like&#xff08;谓词&#xff09;where聚合函数&#xff1a;关于nullgroup byexi…