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_year
	int _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.mfbz.cn/a/787821.html

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

相关文章

SDIO CMD 数据部分 CRC 计算规则

使用的在线 crc 计算工具网址&#xff1a;http://www.ip33.com/crc.html CMD CRC7 计算 如下图为使用逻辑分析仪获取的SDIO读写SD卡时&#xff0c;CMD16指令发送的格式&#xff0c;通过逻辑分析仪总线分析&#xff0c;可以看到&#xff0c;该部分的CRC7校验值得0x05,大多数情况…

说说iOS苹果的“开发者模式”什么时候需要打开 需不需要提前打开

在 iOS 开发过程中&#xff0c;开发者模式&#xff08;Developer Mode&#xff09;是一个非常重要的功能&#xff0c;它允许开发者在设备上运行和调试自己的应用程序。 经常有人私信或在群里问到&#xff0c;“我没有开发者模式&#xff0c;怎么办”&#xff0c;“开发者模式是…

4:表单和通用视图

表单和通用视图 1、编写一个简单的表单&#xff08;1&#xff09;更新polls/detail.html文件 使其包含一个html < form > 元素&#xff08;2&#xff09;创建一个Django视图来处理提交的数据&#xff08;3&#xff09;当有人对 Question 进行投票后&#xff0c;vote()视图…

Github绑定自己的域名

Github绑定自己的域名 1.注册自己的域名2.在GitHUb上创建一个自己的仓库&#xff0c;添加域名2.1 创建仓库2.2 添加域名2.3 在Setting中将域名添加到Custom domain中 3.添加域名解析获取ip地址4.在阿里云修改域名解析记录5.ping 域名即可成功 详细内容可参该博客&#xff1a; …

AutoHotKey自动热键(五)添加WINDOWS秘笈指令-输入瞬间启动功能

在AUTOHOTKEY的使用中,不仅仅可以监听组合热键,还可以监听正常文本击键录入,这是另一种监听方式,比如依次击键jsq之后直接弹出<计算器>工具,或者依次击键sj之后直接输出135****5564的手机号码,等等,这就是autohotkey的录入击键监听,以双冒号为开头:: 因这种录入监听像极了…

Word文件打开密码设置:掌握这两种方法,保护你的文档安全

在日常工作和学习中&#xff0c;我们经常会使用Microsoft Word来创建和编辑文档。有时候&#xff0c;为了保护文档内容不被未经授权的人员查看或修改&#xff0c;我们通常会采用加密的方式来增加其安全性。那么Word文档怎么加密&#xff1f; 方法一&#xff1a;使用Word软件内置…

CTF php RCE (一)

0x01 引言 首先进入题目 应该是大部分都是一段白盒PHP审计&#xff0c;然后我们为了命令执行&#xff0c;绕过或者是钻空子等等操作&#xff0c;来拿到flag 0x02 基础 0x01 传参方式 这里有两个工具&#xff0c;hackbar和burpsuite,这两个工具非常实用 大家可以自己Googl…

力扣第一题

1. 两数之和 提示 给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出 和为目标值 target 的那 两个 整数&#xff0c;并返回它们的数组下标。 你可以假设每种输入只会对应一个答案。但是&#xff0c;数组中同一个元素在答案里不能重复出现。 你可…

OpenFWI代码

重点关注文章第4部分 一、代码模块概览 这一部分了解代码主要实现的功能有哪些。 二、运行 这一部分关注如何跑通。 三、数据集 12个数据集&#xff08;11个2D1个3D&#xff09; 对计算机而言&#xff0c;上述输入、输出维度大小是按次数定义的。 以“Vel&#xff0c;F…

javaweb个人主页设计(html+css+js)

目录 1 前言和要求 1.1 前言 1.2 设计要求 2 预览 2.1 主页页面 2.2 个人简介 2.3 个人爱好 2.4 个人成绩有代码&#xff0c;但是图片已省略&#xff0c;可以根据自己情况添加 2.5 收藏夹 3 代码实现 3.1 主页 3.2 个人简介 3.3 个人爱好 3.4 个人成绩&#xff…

图吧工具箱:装机爱好者必备工具合集

名人说:莫道谗言如浪深,莫言迁客似沙沉。 ——刘禹锡《浪淘沙》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 目录 一、概述二、主要功能1、硬件检测2、测试与故障诊断三、使用方法四、总结很高兴你打开了这篇博客,更多好用的软件工具,请关注我、订阅专栏…

0302GPIO外设输入功能

GPIO外设输入功能 输入部分硬件电路按键简介传感器模块简介按键和传感器模块的硬件电路 C语言的学习C语言数据类型宏定义typedef结构体枚举C语言知识总结 按键控制LED灯&光敏传感器蜂鸣器GPIO总结GPIO使用方法总结模块化编程的方法&#xff1a; 两个程序&#xff1a;按键控…

图像分割-编码解码网络的训练-kreas实现

一、数据集加载&#xff1a; 纯手工打造一个函数用来加载数据&#xff0c;数据分别为image和mask 我们所需要的类型&#xff1a;&#xff08;B数量&#xff0c;长&#xff0c;宽&#xff0c;通道数&#xff09;&#xff0c;只要将数据加载成这样并mask和image对应就行。 第一步…

S271系列RTU在旅游景区人流监控中的应用案例

S271系列RTU在旅游景区人流监控中的应用案例 随着全球旅游业的迅猛发展&#xff0c;旅游景区的管理者越来越关注如何利用先进的技术手段提升游客体验、优化管理效率以及确保安全。S271系列RTU作为一款先进的无线工业物联网设备&#xff0c;在旅游景区的人流监控中展现出了其独…

PTA - 编写函数计算圆面积

题目描述&#xff1a; 1.要求编写函数getCircleArea(r)计算给定半径r的圆面积&#xff0c;函数返回圆的面积。 2.要求编写函数get_rList(n) 输入n个值放入列表并将列表返回 函数接口定义&#xff1a; getCircleArea(r); get_rList(n); 传入的参数r表示圆的半径&#xff0c…

批量下载手机中APP程序中文件

需求 利用 adb pull 下载手机中app的某目录 adb pull 命令本身不支持直接下载整个目录&#xff08;文件夹&#xff09;及其所有子目录和文件作为一个单一的操作。但是&#xff0c;可以通过一些方法来间接实现这一目的。 方法 1. 首先将要下载的目录进行 tar 打包 # 在 And…

2020 ICPC Shanghai Site B. Mine Sweeper II 题解 构造 鸽巢原理

Mine Sweeper II 题目描述 A mine-sweeper map X X X can be expressed as an n m n\times m nm grid. Each cell of the grid is either a mine cell or a non-mine cell. A mine cell has no number on it. Each non-mine cell has a number representing the number of…

Raylib 实现超大地图放大缩小与两种模式瓦片地图刷新

原理&#xff1a; 一种刷新模式&#xff1a; 在宫格内整体刷新&#xff0c;类似九宫格移动到边缘&#xff0c;则九宫格整体平移一个宫格&#xff0c;不过这里是移动一个瓦片像素&#xff0c;实际上就是全屏刷新&#xff0c;这个上限是 笔记本 3060 70帧 100*100个瓦片每帧都…

《赌局的诱惑》-反赌反诈剧情脚本

场景1&#xff1a; 一家普通公司的休息室&#xff0c;有一张桌子&#xff0c;上面摆放着扑克牌和一些现金。墙上挂着一个时钟&#xff0c;显示时间是下午5点。 人物&#xff1a; 张伟&#xff1a;新员工&#xff0c;被同事拉入赌局。 赵刚&#xff1a;资深员工&#xff0c;赌…

UE5.3-基础蓝图类整理一

常用蓝图类整理&#xff1a; 1、获取当前关卡名&#xff1a;Get Current LevelName 2、通过关卡名打开关卡&#xff1a;Open Level(by name) 3、碰撞检测事件&#xff1a;Event ActorBeginOverlap 4、获取当前player&#xff1a;Get Player Pawn 5、判断是否相等&#xff1…