C++初探究(2)

引用

对于一个常量,想要将其进行引用,则使用普通的引用相当于权限扩大(常量为只读,但此处的引用参数为可读可写),C++编译器会报错. 例如:

const int a = 10;int& ra = a;//权限放大,会报错

所以C++中存在这样的语法: 

const引用

在引用前加上const即为const引用:

//此时a只读不可写const int a = 10;const int& ra = a;

此时引用变量名也为常量(只读)

常量引用可以直接引用常量:
const int& rc = 30;
 常量引用计算式或类型转换

类似 int& rb = a*3; double d = 12.34; int& rd = d;这样的式,都会将结果保存到临时变量中,而C++规定临时变量具有常性,所以需要使用常量引用.

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;

注意

//此时b可读可写int b = 20;const int& rb = b;//权限缩小,可以实现b++;rb++;//此处会报错

 我们设置一个变量b,并使用常量引用创造rb,此时的rb为只读,但b为可读可写,这就造成了权限缩小,可以实现.;但此时我们对b进行++,会发现b仍会改变,且常量rb也会改变,这是因为我们创建的常量是rb,而不是b,所以我们不能对rb进行操作,但可以对b进行操作.

引用与指针的关系

在C++中,引用与指针相辅相成,虽有其类似之处,但各有其特点,不可替代.

• 语法概念上引⽤是⼀个变量的取别名不开空间,指针是存储⼀个变量地址,要开空间。
• 引⽤在定义时必须初始化,指针建议初始化,但是语法上不是必须的。
• 引⽤在初始化时引⽤⼀个对象后,就不能再引⽤其他对象;⽽指针可以在不断地改变指向对象。
• 引⽤可以直接访问指向对象,指针需要解引⽤才是访问指向对象。
• sizeof中含义不同,引⽤结果为引⽤类型的⼤⼩,但指针始终是地址空间所占字节个数(32位平台下
占4个字节,64位下是8byte)
• 指针很容易出现空指针和野指针的问题,引⽤很少出现,引⽤使⽤起来相对更安全⼀些。

内联(inline)

1.⽤inline修饰的函数叫做内联函数,编译时C++编译器会在调⽤的地⽅展开内联函数,这样调⽤内

联函数就需要建⽴栈帧了,就可以提⾼效率。

2.C语言会在预处理时展开内联函数,而inline对于编译器来说只是建议,若函数递归次数过深或函数语句较多编译器将不会展开内联函数。

3.宏函数的实现是复杂且易错的,C++设计内联函数是为了替代宏函数的.这里我们举个例子:写一个相加函数

#define Add(x, y) ((a) + (b))

这里提出三个问题: 

 为什么不能加分号?为什么要加⾥⾯的括号?为什么要加外⾯的括号?

A.宏函数是展开,所以在宏函数中加分号,当用于if else语句时也会带上';', 编译器将会报错

B.这里举一个反例:

int ret = ADD(1, 2);cout << ADD(1, 2) << endl;
cout << ADD(1, 2)*5 << endl;

在宏函数中此处语句会被替换成1 + 2 * 5不是我们想要的值.

C.这里举一个反例:

int x = 2, y = 6;ADD(x & y, x | y); // -> (x&y+x|y)
return 0;

此处会先进行加法运算而不是先进行按位与和按位或运算,与我们预期相悖.

4.inline函数是不能存在于两个文件中的,所以对于inline函数,我们直接在头文件中实现即可.

在c语言中,我们已经学过一种空指针“NULL”,NULL实际是个宏函数:

#ifndef NULL#ifdef __cplusplus#define NULL 0#else#define NULL ((void *)0)#endif
#endif

但在C++中,NULL可能被定义为常量0,所以C++引入一个专门表示空指针的关键字:

新的空指针(nullptr)

        C++11中引⼊nullptr,nullptr是⼀个特殊的关键字,nullptr是⼀种特殊类型的字⾯量,它可以转换成任意其他类型的指针类型。使⽤nullptr定义空指针可以避免类型转换的问题,因为nullptr只能被隐式地转换为指针类型,⽽不能被转换为整数类型。

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(int
//x),因此与程序的初衷相悖。f(NULL);f((int*)NULL);
//  编译报错:error C2665: “f”: 2 个重载中没有⼀个可以转换所有参数类型
//  f((void*)NULL);f(nullptr);
}

此处NULL被错误的读成了0,导致了错误;且nullptr只能转换为指针类型,而不能转换为整型.

类和对象 

class Stack
{
}

 类的使用

        我们以class Stack为例,class为类的定义类的关键字,此处的Stack为类的名字(可以自定义),类可以像C语言中的结构体一样存储成员,但与C语言中的结构体不同的是,类可以存储函数(被称为类的方法或成员函数).例如:

class Stack
{void Init(int n = 4){array = (int*)malloc(sizeof(int) * n);if (nullptr == array){perror("malloc申请空间失败");return;}capacity = n;top = 0;}int a;int b;
};//分号不要忘了加

其中的Init()即为类的方法,a和b即为成员.

并且定义在类中的函数默认是内联函数(inline).

访问限定符

• C++⼀种实现封装的⽅式,⽤类将对象的属性与⽅法结合在⼀块,让对象更加完善,通过访问权限选择性的将其接⼝提供给外部的⽤户使⽤。


• public修饰的成员在类外可以直接被访问;protected和private修饰的成员在类外不能直接被访
问,protected和private是⼀样的,以后继承章节才能体现出他们的区别。


• 访问权限作⽤域从该访问限定符出现的位置开始直到下⼀个访问限定符出现时为⽌,如果后⾯没有访问限定符,作⽤域就到 }即类结束。


• class定义成员没有被访问限定符修饰时默认为private,struct默认为public。


• ⼀般成员变量都会被限制为private/protected,需要给别⼈使⽤的成员函数会放为public。   

     

例如:

class Date
{
public:void Init(int year, int month, int day){_year = year;_month = month;_day = day;}private:// 为了区分成员变量,⼀般习惯上成员变量// 会加⼀个特殊标识,如_ 或者 m开头int _year; // year_ m_yearint _month;int _day;
};

 相对于C语言,C++中的struct结构体也可以包含函数了,可以包含函数的结构体与类的区别就是类中不写访问限定符即为private作用域,而struct中不写访问限定符即为public作用域.

我们来调用一下public作用域中的函数:

int main()
{Date d;//C++可以直接用类名(类名代表类型)//并且兼容C的struct用法d.Init(2024, 7, 9);return 0;
}

 而想要调用private中的成员,则需要使用:

类域(class)

• 类定义了⼀个新的作⽤域,类的所有成员都在类的作⽤域中,在类体外定义成员时,需要使⽤ :: 作⽤域操作符指明成员属于哪个类域。


• 类域影响的是编译的查找规则,下⾯程序中Init如果不指定类域Stack,那么编译器就把Init当成全
局函数,那么编译时,找不到array等成员的声明/定义在哪⾥,就会报错。指定类域Stack,就是知
道Init是成员函数,当前域找不到的array等成员,就会到类域中去查找。

举个例子,我们想要调用Stack域中的函数Init, 就应该这样:

void Stack::Init(int n)
{
}
函数的声明与定义分离

函数的声明:

class Stack
{
public:// 成员函数void Init(int n = 4);
private:// 成员变量int* array;size_t capacity;size_t top;
};

而我们如果想要对函数定义,则需要专门使用类域来定义函数.

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

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

相关文章

Python大数据分析——决策树和随机森林

Python大数据分析——决策树和随机森林 决策树决策树节点字段的选择信息熵条件熵信息增益信息增益率 基尼指数条件基尼指数基尼指数增益 决策树函数 随机森林函数 决策树 图中的决策树呈现自顶向下的生长过程&#xff0c;深色的椭圆表示树的根节点&#xff1b;浅色的椭圆表示树…

Java项目:基于SSM框架实现的农家乐信息管理平台含前后台【ssm+B/S架构+源码+数据库+答辩PPT+开题报告+毕业论文】

一、项目简介 本项目是一套基于SSM框架实现的农家乐信息管理平台 包含&#xff1a;项目源码、数据库脚本等&#xff0c;该项目附带全部源码可作为毕设使用。 项目都经过严格调试&#xff0c;eclipse或者idea 确保可以运行&#xff01; 该系统功能完善、界面美观、操作简单、功…

招投标信息采集系统:让您的企业始终站在行业前沿

一、为何招投标信息如此关键&#xff1f; 在经济全球化的大背景下&#xff0c;招投标活动日益频繁&#xff0c;成为企业获取项目、拓展市场的主流方式之一。招投标信息采集&#xff0c;作为企业战略决策的前置环节&#xff0c;其重要性不言而喻。它不仅关乎企业能否第一时间发…

WPF 初识依赖属性

依赖属性的意义和作用 核心模块内存共享&#xff0c;节省空间数据绑定、样式、模板、动画。。。。如果没有依赖属性&#xff0c;这个框架就是一个控件框架 相当于Winform 依赖属性的基本定义 基本过程&#xff1a;声明、注册、包装 在需要写依赖属性的类中&#xff0c;继承…

快速将一个网址打包成一个exe可执行文件

一、电脑需要node环境 如果没有下面有安装教程&#xff1a; node.js安装及环境配置超详细教程【Windows系统安装包方式】 https://blog.csdn.net/weixin_44893902/article/details/121788104 我的版本是v16.13.1 二、安装nativefier 这是一个GitHub上的开源项目&#xff1a…

C 语言函数

1.0 函数的创建和使用 在C语言中&#xff0c;函数是一种封装了特定功能的代码块&#xff0c;可以被程序中的其他部分调用。函数可以接受输入参数&#xff0c;并且可以返回一个值。定义一个函数的基本语法如下 #define _CRT_SECURE_NO_WARNINGS #include "stdio.h" …

阿里云人工智能平台PAI部署开源大模型chatglm3之失败记录--update:最后成功了!

想学习怎么部署大模型&#xff0c;跟着网上的帖子部署了一个星期&#xff0c;然而没有成功。失败的经历也是经历&#xff0c;记在这里。 我一共创建了3个实例来部署chatglm3&#xff0c;每个实例都是基于V100创建的&#xff08;当时没有A10可选了&#xff09;&#xff0c;其显…

x86芯片定制,Ethercat芯片定制,IP服务,适用于运动控制,工业总线等软硬一体机

x86芯片定制&#xff0c;Ethercat芯片定制 X86平台 我们的研发工程师已经积累了非常丰富的主板、整机设计经验&#xff0c;对接您的产品规格场景需求&#xff0c;快速交付样机&#xff0c;包含主板、BOX整机、平板电脑、CPCI等形态产品。降本、长生命周期、快速交付、及时响应…

IEC62056标准体系简介-2.IEC62056标准体系及对象标识系统(OBIS)

1. IEC 62056标准体系 IEC 62056标准体系目前共包括六部分&#xff0c;见图1&#xff1a; 第61部分&#xff1a;对象标识系统第62部分&#xff1a;接口类第53部分&#xff1a;COSEM应用层第46部分&#xff1a;使用HDLC&#xff08;High Level Data Link Control&#xff09;协…

Linux多进程和多线程(八)多线程

多线程 线程定义线程与进程线程资源 线程相关命令 pidstat 命令 top 命令ps 命令常见的并发方案 1. 多进程模式2. 多线程模式 创建线程 1. pthread_create() 示例:创建一个线程 2. pthread_exit() 退出线程3. pthread_join() 等待线程结束 示例: 线程分离 创建多个线程 示例 1:…

前端面试题35(在iOS和Android平台上,实现WebSocket协议有哪些常见的库或框架?)

在iOS和Android平台上&#xff0c;实现WebSocket协议有许多成熟且被广泛使用的库和框架。下面是一些推荐的选项&#xff1a; iOS 平台 SocketRocket 简介&#xff1a;这是由Facebook开源的库&#xff0c;专门为iOS和Mac OS X设计&#xff0c;提供WebSocket连接的功能。它基于S…

Blender新手入门笔记收容所(一)

基础篇 基础操作 视角的控制 控制观察视角&#xff1a;鼠标中键平移视图&#xff1a;Shift鼠标中键缩放视图&#xff1a;滚动鼠标中键滚轮 选中物体后&#xff1a;移动物体快捷键G&#xff0c;移动后单击鼠标就会定下来。 进入移动状态后&#xff1a;按Y会沿着Y轴移动进入移动…

HW期间——应急响应

01HW中应急响应的流程 001应急响应所处位置&#xff08;应急处置组&#xff09; 监控研判组发现的一些安全时间提供给应急处置组&#xff0c;应急处置组通过上机取证把线索给到溯源反制组。但是溯源反制组可能已经没有了&#xff0c;有些单位有&#xff0c;有些单位取消了。有…

Python神经模型评估微分方程图算法

&#x1f3af;要点 &#x1f3af;神经网络映射关联图 | &#x1f3af;执行时间分析 | &#x1f3af;神经网络结构降维 | &#x1f3af;量化图结构边作用 | &#x1f3af;数学评估算法实现 &#x1f36a;语言内容分比 &#x1f347;Python随机梯度下降算法 随机梯度下降是梯度…

matlab仿真 通信信号和系统分析(下)

&#xff08;内容源自详解MATLAB&#xff0f;SIMULINK 通信系统建模与仿真 刘学勇编著第三章内容&#xff0c;有兴趣的读者请阅读原书&#xff09; 一、离散傅里叶变换 clear all n0:30;%信号的时间范围 xsin(0.2*n).*exp(-0.1*n); k0:30;%频率范围 N31; Wnkexp(-j*2*pi/N).…

解决本地操作云服务器上的Redis

方案一&#xff1a;开放Redis默认端口&#xff0c;本地通过公网IP端口号的形式访问。 方案二&#xff1a;每次将本地编写好的Java代码打包&#xff0c;放在云服务器上运行。 方案三&#xff1a;配置ssh端口转发&#xff0c;把云服务器的redis端口&#xff0c;映射到本地主机。 …

【大模型】微调实战—使用 ORPO 微调 Llama 3

ORPO 是一种新颖微调&#xff08;fine-tuning&#xff09;技术&#xff0c;它将传统的监督微调&#xff08;supervised fine-tuning&#xff09;和偏好对齐&#xff08;preference alignment&#xff09;阶段合并为一个过程。这减少了训练所需的计算资源和时间。此外&#xff0…

使用微pe装系统

本文仅作为记录&#xff0c;不作为教程。 今天心血来潮想下点游戏玩玩&#xff0c;一看之前分的200gc盘已经红了&#xff0c;再加上大学之后这个笔记本已经用得很少了&#xff0c;于是打算重装电脑。 参考: 微PE辅助安装_哔哩哔哩_bilibil… 1.下载微pe和win10系统到U盘 我这…

Xilinx zc706 USB电路解析

作者 QQ群&#xff1a;852283276 微信&#xff1a;arm80x86 微信公众号&#xff1a;青儿创客基地 B站&#xff1a;主页 https://space.bilibili.com/208826118 参考 USB OTG检测原理 USB3320 USB_ID为低电平时候&#xff0c;为host模式&#xff0c;USB_ID为悬空&#xff08;高…

python-23-零基础自学python open()和replace()函数运用

学习内容&#xff1a;《python编程&#xff1a;从入门到实践》第二版练习10-2 知识点&#xff1a; 打开文件&#xff0c;replace()替换文件内容&#xff0c;open(), 练习内容&#xff1a; 练习10-2:C语言学习笔记 可使用方法replace()将字符串中的特定单词都替换为另一个单…