【C++入门(下)】—— 我与C++的不解之缘(二)

简介: 【C++入门(下)】—— 我与C++的不解之缘(二)

前言

       接上篇,继续来学习C++,本篇内容大概有 引用inlinenullptr

六、引用:

       6.1、引用的定义

       引用不是新定义一个变量,而是给已存在的变量取了一个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量公用一块内存空间。

类型 & 引用别名 = 引用对象 ;

int main()
{
  int a = 10;
  
  int& b = a;//这里b是a的别名
  //也可以给b去别名
  int& c = b;
  int& d = c;
 
  cout << a << endl;
  cout << b << endl;
  cout << c << endl;
  cout << d << endl;
  return 0;
}

       6.2、引用的特性

  1. 引用在定义时必须初始化
  2. 一个变量可以有多个引用
  3. 引用一旦引用一个实体,就不能再引用其他实体
int main()
{
  //int& b; 必须初始化
 
  int a = 10;
  int& b = a;
 
  int c = 9;
  b = c;// b=c => a=c ?
  return 0;
}
'
运行
运行

       6.3、引用的使用

  • 引用在实践中主要是引用参数和引用做返回值中减少拷贝提高效率和改变对象时同时改变被引用对象时同时改变被引用对象。
  • 引用传参跟指针传参功能是类似的,引用传参相对更加方便一些。
  • 引用和指针在实践中相辅相成,功能有重叠性,但是各有特点,互相不可替代。C++的引用跟其他语言的引用(如java)是有很大区别的,除了用法,最大的差别(C++引用定义不能改变指向,而java的引用可以改变指向)。
  • 在一些主要用C语言代码实现版本的数据结构教材中,使用C++引用代替指针传参,目的是简化程序,避开复杂的指针。

引用作为函数参数:

void Swap(int& rx, int& ry)
{
  int tmp = rx;
  rx = ry;
  ry = tmp;
}
int main()
{
  int x = 1, y = 9;
  cout << x << " " << y << endl;
  Swap(x, y);
  cout << x << " " << y << endl;
  return 0;
}

引用作为函数返回值:

       例如,在栈数据结构中,我们取栈顶数据后直接修改:

int& STTop(ST& rs)
{
  assert(rs.top > 0);
  return rs.a[rs.top];
}
 
int main()
{
  cout << STTop(st1) << endl;
  STTop(st1) += 10;
  cout << STTop(st1) << endl;
  return 0;
}

       6.4、const 引用

       可以引用一个 const 对象,但是必须用 const 引用。const 引用也可以引用配套对象,(对象的访问权限在引用过程中可以缩小,但是不能放大)。

       const 引用需要注意:类似(int& rb = a*3; double d = 13.14; int& rd=d;)这样一些情况下 a*3的结果保存在一个临时变量中,int& rd = d也是类似,(在类型转换中会产生一些临时对象存储中间值,也就是 rd 与 rd引用的都是临时对象,而C++规定临时对象具有常性,所以这里就对权限进行了放大,必须要常引用才行)。

       这里所说的临时变量就是编译器需要一个空间暂存表达式的求值结果时临时创建的一个未命名的对象(C++中把这个未命名的对象叫做临时对象)。

int main()
{
  const int a = 10;
  //这里对a访问的权限放大
  //int& ra = a;
 
  const int& ra = a;
  //这里 改变const定义的常量
  //ra++;//ra = 0;
 
  int b = 1;
  const int& rb = b;
  //const 修饰 引用rb  不能修改常量
  //rb++;
  return 0;
}
'
运行
运行

类型转换:

int main()
{
  int a = 10;
  const int& ra = 30;
  // 编译报错: “初始化”: 无法从“int”转换为“int &”
  // int& rb = a * 3;
  const int& rb = a * 3;
  double d = 12.34;
  // 编译报错:“初始化”: 无法从“double”转换为“int &”
  // int& rd = d;
  const int& rd = d;
  return 0;
}
'
运行
运行

       6.5、指针与引用的关系

       C++中指针和引用,在实践中它们相辅相成,功能有重叠性,但是它们也各有自己的特点,互相不可替代。

  • 在语法概念上,引用是一个变量的取别名,不开辟空间,;而指针是存储地址的变量,要开辟空间。
  • 引用在定义时必须初始化,指针建议初始化(但是语法上不是必须的)。
  • 引用在初始化引用时引用一个对象后,就不能再引用其他对象;而指针可以不断改变指向的对象。(这里题外话:引用就像纯爱战士(深情专一))。
  • 引用可以直接访问指向对象,而指针需要解引用才是访问对象。
  • sizeof 中含义不同,引用结果为引用类型的大小,而指针始终是地址空间所占字节个数(32位平台下占4个字节,64位平台下占8个字节)。
  • 指针很容易出现空指针和野指针的情况,引用很少出现,引用使用起来相对安全。

七、inline

  • 用inline修饰的函数叫做内联函数,编译时C++编译器会在调用的地方展开内联函数,这样调用内联函数时就不需要栈帧了,提高效率。
  • inline对于编译器而言只是一个建议,也就是说,加了inline编译器也可以选择在调用的地方不展开,不同的编译器关于inline什么情况展开各不相同,因为C++标准没有定义这个。(inline适用于频繁调用的短小函数,对于递归函数,代码相对多的函数,加上inline会被编译器忽略)。

       C语言实现宏函数也会在预处理的时候展开,但是宏函数实现很复杂并且容易出错,且不方便调试,C++设计inline目的就是代替C的宏函数。

       inline不建议声明和定义分离到两个文件,分离会导致连接出错。(inline被展开,就没有了函数的地址,链接时会报错)。

       VS中debug版本默认不展开inline,(方便调试),如果想要进行展开可以进行一下设置

八、nullptr

       在C语言中,空指针是NULL,但是其实NULL是一个宏(在stddef.h)中

#ifndef NULL
  #ifdef __cplusplus
    #define NULL 0
  #else
    #define NULL ((void *)0)
  #endif
#endif
  • C++中NULL可能被定义为字面常量 0,或者C语言中被定义为无类型的指针(void*)的常量。这样在使用时,都会有一些不可避免的麻烦,
  • C++ 11 引入了nullptr,nullptr是一个特殊的关键字,nullptr是一种特殊类型的字面量,它可以转换成任意类型的指针类型,使用nullptr定义空指针可以避免类型转换的问题,因此nullptr只能被隐式的转换成指针,而不能被转换成整数类型。
#include<iostream>
using namespace std;
void f(int x)
{
  cout << "f(int x)" << endl;
}
void f(int* ptr)
{
  cout << "f(int* ptr)" << endl;
}
int main()
{
  f(0);/*本想通过f(NULL)调用指针版本的f(int*)函数,
  但是由于NULL被定义成0,调用了f(intx)。*/
  f(NULL);
  f((int*)NULL);
  
  //f((void*)NULL);
  // 编译报错:error C2665: “f”: 2 个重载中没有一个可以转换所有参数类型
  // f((void*)NULL);
  
  f(nullptr);
  return 0;
}


相关文章
|
25天前
|
弹性计算 人工智能 架构师
阿里云携手Altair共拓云上工业仿真新机遇
2024年9月12日,「2024 Altair 技术大会杭州站」成功召开,阿里云弹性计算产品运营与生态负责人何川,与Altair中国技术总监赵阳在会上联合发布了最新的“云上CAE一体机”。
阿里云携手Altair共拓云上工业仿真新机遇
|
17天前
|
存储 关系型数据库 分布式数据库
GraphRAG:基于PolarDB+通义千问+LangChain的知识图谱+大模型最佳实践
本文介绍了如何使用PolarDB、通义千问和LangChain搭建GraphRAG系统,结合知识图谱和向量检索提升问答质量。通过实例展示了单独使用向量检索和图检索的局限性,并通过图+向量联合搜索增强了问答准确性。PolarDB支持AGE图引擎和pgvector插件,实现图数据和向量数据的统一存储与检索,提升了RAG系统的性能和效果。
|
4天前
|
JSON 自然语言处理 数据管理
阿里云百炼产品月刊【2024年9月】
阿里云百炼产品月刊【2024年9月】,涵盖本月产品和功能发布、活动,应用实践等内容,帮助您快速了解阿里云百炼产品的最新动态。
阿里云百炼产品月刊【2024年9月】
|
1天前
|
人工智能 Rust Java
10月更文挑战赛火热启动,坚持热爱坚持创作!
开发者社区10月更文挑战,寻找热爱技术内容创作的你,欢迎来创作!
253 12
|
19天前
|
人工智能 IDE 程序员
期盼已久!通义灵码 AI 程序员开启邀测,全流程开发仅用几分钟
在云栖大会上,阿里云云原生应用平台负责人丁宇宣布,「通义灵码」完成全面升级,并正式发布 AI 程序员。
|
21天前
|
机器学习/深度学习 算法 大数据
【BetterBench博士】2024 “华为杯”第二十一届中国研究生数学建模竞赛 选题分析
2024“华为杯”数学建模竞赛,对ABCDEF每个题进行详细的分析,涵盖风电场功率优化、WLAN网络吞吐量、磁性元件损耗建模、地理环境问题、高速公路应急车道启用和X射线脉冲星建模等多领域问题,解析了问题类型、专业和技能的需要。
2579 22
【BetterBench博士】2024 “华为杯”第二十一届中国研究生数学建模竞赛 选题分析
|
3天前
|
存储 人工智能 搜索推荐
数据治理,是时候打破刻板印象了
瓴羊智能数据建设与治理产品Datapin全面升级,可演进扩展的数据架构体系为企业数据治理预留发展空间,推出敏捷版用以解决企业数据量不大但需构建数据的场景问题,基于大模型打造的DataAgent更是为企业用好数据资产提供了便利。
169 2
|
1天前
|
编译器 C#
C#多态概述:通过继承实现的不同对象调用相同的方法,表现出不同的行为
C#多态概述:通过继承实现的不同对象调用相同的方法,表现出不同的行为
101 65
|
21天前
|
机器学习/深度学习 算法 数据可视化
【BetterBench博士】2024年中国研究生数学建模竞赛 C题:数据驱动下磁性元件的磁芯损耗建模 问题分析、数学模型、python 代码
2024年中国研究生数学建模竞赛C题聚焦磁性元件磁芯损耗建模。题目背景介绍了电能变换技术的发展与应用,强调磁性元件在功率变换器中的重要性。磁芯损耗受多种因素影响,现有模型难以精确预测。题目要求通过数据分析建立高精度磁芯损耗模型。具体任务包括励磁波形分类、修正斯坦麦茨方程、分析影响因素、构建预测模型及优化设计条件。涉及数据预处理、特征提取、机器学习及优化算法等技术。适合电气、材料、计算机等多个专业学生参与。
1578 16
【BetterBench博士】2024年中国研究生数学建模竞赛 C题:数据驱动下磁性元件的磁芯损耗建模 问题分析、数学模型、python 代码
|
4天前
|
Linux 虚拟化 开发者
一键将CentOs的yum源更换为国内阿里yum源
一键将CentOs的yum源更换为国内阿里yum源
257 2