【C++从0到1】C++入门(上篇)类入门篇

2023-11-20


前言

C++入门是很多人头疼的问题,今日就与博主一同学习一些比较简单的基本概念,这些在之后很多地方的作用是十分大的。
看完之后,相信你会受益匪浅!!


一、命名空间

命名空间是什么,为什么要存在命名空间,首先我们如果以前有看过c++的代码一定少不了这两句。

#include<iostream>
using namespace std;

这个大家想必都看过,using在这里实际上就是展开命名空间的内容。

命名空间就是一个域,与外界隔离,使用域当中的东西要通过(域名+::)在这里插入图片描述在这里插入图片描述

当我们要使用当前引入库函数当中的函数名作为变量时,例如:如果我们引入头文件#include<stdlib.h>,我们会发现我们使用rand作为变量名会出错在这里插入图片描述

这是因为我们rand在stdlib中是作为一个函数存在的,我们如果引了头文件,相当于在预处理的时候就会将头文件展开,我们就会看到rand作为函数的声明及实现。在这里插入图片描述

这个时候我们就无法使用这个rand,命名空间却能帮我们解决在这里插入图片描述

从上图可以看出,命名空间不受到其他域当中影响,因为在全局域展开并不会影响到命名空间。但是如果我们不展开命名空间的话,调用命名空间内部的函数时我们都要采用域限定符,所以我们在进行一些日常练习时才会去进行命名空间的展开。
在这里插入图片描述
在这里插入图片描述

需要注意的就是,如果有同名的命名函数,他们就会被合在一起。在这里插入图片描述
对于命名空间,内部也可以在嵌套定义命名空间,使用的时候也要注意加上域作用限定符。在这里插入图片描述

总结:我们使用命名空间的时候可以进行部分展开,对于常用的函数展开,这是一种折中的解决方案。在这里插入图片描述


二、缺省函数

常见使用在这里插入图片描述
在这里插入图片描述

在模拟顺序表的初始化的时候,我们可以用缺省参数控制我们要申请多大的空间,如果没有传参数,我们可以默认帮它设置。其中我们上面演示的为半缺省参数。

  1. 半缺省参数必须从右往左依次来给出,不能间隔着给
  2. 缺省参数不能在函数声明和定义中同时出现

解释第一条:因为如果从左开始给的话,如果我们左边想要默认的缺省值,就不合理了。
解释第二条:倘若声明和定义当中给的缺省值不一样,编辑器无法判断,所以制止这种写法,倘若要使用,则参照下图。在这里插入图片描述


三、 函数重载

3.1常见使用

在这里插入图片描述
刚刚谈完的命名空间中一个域中不能出现重复的定义,但是c++在这里,允许了函数重载,只要函数的顺序(不同类型之间),类型不同,都可以造成函数重载。

上面这三种均不造成重载,现在来说明原因。原因与c++当中为何支持函数重载有关,相信看了下面你就能明白。


3.2重载底层实现

提前说明,以下为linux的解释说明,并且文件后缀不代表他是否为cpp文件,而是根据我们所调用的编辑器决定的。
先说结论:是因为他们的函数名修饰规则不同导致的。

我们先来看看linux下对于c的函数名和cpp当中的函数名在编译阶段是怎样的,这里我们用的是objudump -S,查看我们的.o文件

我们能在这里观察到对于linux平台下,链接时我们的函数是没有经过任何修饰的,通过这样的函数名在链接的时候重定位将函数的地址再填进去。在c中,这样子当我们重载的时候,两个同名的add即便构成重载,却因为两个相同的add构成了不确定导致无法进行链接在这里插入图片描述
而c++当中对于函数进行了修饰,并且它的修饰规则比较简单_Z是固定的前缀,3表示函数名的长度,我们Add的长度正好是3,而剩下的ii/dd则就是参数名称。
在这里插入图片描述
在这里插入图片描述


3.3返回值不纳入重载原因

那么有人可能会想,为什么设计的时候不把返回值也作为函数重载的依据呢,设想一下,假如我们在函数名前面假如返回值的首字母作为修饰函数名,下面这种情况是不是也是存在异议的,也就是我们底层设计的时候虽然是可以支持到函数返回值也来修饰函数名,从语法层面,编辑器不能通过此特征来判断调用哪个函数。

在这里插入图片描述


四、extren C

我们在日常中如果采用c语言去写一个项目,如果我们要利用c++库的话,根据上面函数重载,我们c语言在链接时通过自己的函数名是没办法找到对应的c++的函数名的,而c++在c语言后面诞生,所以采用c++写的项目,调用c的库的时候是可以直接找到的。所以我们编写c++的库的时候,为了照顾到我们用纯c写项目的,就会在该函数的声明处加上extern “C”,这样c++和c都能同时调到这个函数。

比如谷歌提供tcmalloc库中就有若干函数如此。

在这里插入图片描述


五、引用

5.1常见使用

在这里插入图片描述
可以看出a为b的一个引用,别名,语法上是不占空间的,我们通过取地址也可以看出a和b指向的都是同一块内存。

在这里插入图片描述
引用的特点:引用必须初始化。引用只能对一块空间,不像指针可以转换指向内容。 一个变量可以有多个引用。


观察下面代码:

int main()
{
//这里是b赋值给a,还是a是b的引用呢?
	int b = 10;
	int& a = b;
	int c = 20;
	a = c;
	return 0;
}

答案揭晓:这里是b赋值给a。
在这里插入图片描述
因为我们接下来要讲到引用返回会遇到的种种情况,所以我们在这里先讲述临时变量是一个怎样的存在。


5.2临时变量的作用

思考这里的ret是怎么返回回去的,在函数栈帧中提到了调用完函数之后,空间会被释放,我们return ret 的时候他是将ret返回吗?不是的,因为ret在Add的栈帧中,如果他返回就会造成空间的越界访问。那么他是如何返回的呢。

答案:当返回的数据大小在4,8字节的情况下通常是由我们的寄存器eax带回来,如果超过这个范围的话,就会在main函数的栈帧中提前开设一块跟返回值的一份临时拷贝。临时数据具有常性。在这里插入图片描述
在这里插入图片描述

带回我们的结构体做了若干操作,我们这里不详细讲解。对上面的答案进行简单的论证。

在这里插入图片描述

强制类型转换和隐式类型转换都是会创建一个临时变量进行接受的,像下面这张图,我们的r虽然是i的引用,但是他们却不是指向同一块空间的,而这里的r是指向谁了呢?就是我们的一个临时变量,临时变量具有常性,我们不能对他进行修改,所以我们要添加const表示只对该变量有读取的权限!
在这里插入图片描述

常引用如下:
在这里插入图片描述

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

引用和指针在sizeof中含义不同:引用结果为引用类型的大小(与类型有关),但指针始终是地址空间所占字节个数(32位平台下占4个字节),即与平台有关。


5.3引用返回常见错误

引用有作为参数,和返回值的两大作用,那么使用的时候返回值这块容易犯错误。

int& Add(int x, int y)
{
	int ret = x + y;
	return ret;
}
int main()
{
	int sum = Add(1, 2);
	Add(3, 4);
	cout << "Add(1,2): is " << sum << endl;
	return 0;
}

虽然上面的代码运行的结果是正确的,但是存在着很大的安全隐患,Add这个栈帧销毁过后再去访问,倘若系统对于回收的空间会进行处理的话,这块空间上的值就是随机值,vs2019在这块对于回收的内存是没有做处理的。
在这里插入图片描述
知道了上面的结论,再来看下面这段代码:只改了这一处返回值,这时候会发生什么呢?

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

甚至当你在Add那块空间被cout给覆盖之后,ret的内存空间甚至有可能是一些奇奇怪怪的值。
在这里插入图片描述

结论:对于引用返回,返回的对象必须是栈帧销毁后还存在的。全局,静态,未销毁的函数栈帧当中的都是可以的!!

5.4指针与引用

如图:两者底层实现差不多,引用是用指针模拟的。
在这里插入图片描述


六、内联函数

inline是一种以空间换时间的做法,省去调用函数额开销。所以代码很长或者有循环/递归的函数不适宜 使用作为内联函数。
inline对于编译器而言只是一个建议,编译器会自动优化,如果定义为inline的函数体内有循环/递归等 等,编译器优化时会忽略掉内联。
inline不建议声明和定义分离,分离会导致链接错误。因为inline被展开,就没有函数地址了,链接就会找不到。

内联函数替代宏的原因

#define SWAP(T,m,n) {T s; s=m, m=n, n=s;}
//#define Add(a,b) a+b
//#define Add(a,b) (a+b)
//#define Add(a,b) ((a)+(b))

int main()
{
	int a = 0;
	int b = 1;
	//宏的本质是替换,得看替换之后合不合理!!
	//{T s; s=m, m=n, n=s;}
	SWAP(int,a,b);
	cout << a <<" "<< b << endl;
	return 0;
}

因为宏虽然功能强大,但是在使用的时候缺少类型检查,调试不方便,使用的比较别扭等因素,所以我们c++引入内联函数,在调用的地方展开。但是对编辑器只是一种建议。
c++当中建议用const,enum替换宏常量,内联函数替换宏函数。


七、nullptr

在这里插入图片描述
c++标准将NULL定义为0,通常情况下按照c语言,int* p=NULL,还是没有错的,但是在下面这种情况会有异议。所以我们推荐c++当中使用nullptr作为空指针。
在这里插入图片描述


总结

c++的入门就到这里啦,下一章会描述类和对象。
三连支持一下吧!!!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【C++从0到1】C++入门(上篇)类入门篇 的相关文章

  • 为什么通过派生类对基类的引用与 :: - 运算符不明确?

    所以我想知道为什么以下钻石问题的代码片段无法编译 我知道这个问题通常是通过虚拟继承来解决的 我不是故意使用它的 该代码只是为了展示我的问题 即为什么编译器称此不明确 因此 我在 struct Base 中声明了两个成员变量 因为这两个子类
  • 是否可以从 C++ 应用程序调用 C# 应用程序?

    我是一名编程学生 现在我已经上了两门 C 课程 这个学期我将参加我的第一门 C 课程 出于好奇 是否可以从 C 应用程序调用 C 应用程序 如果是的话 是否还可以检查运行该程序的计算机是否具有 NET框架 我只是很好奇 我想如果可能的话 这
  • c# 从另一个类中的另一个静态事件引发事件

    需要帮助从另一个班级调用事件 我有已声明事件的课程 public class MxPBaseGridView GridView public event AddNewItemsToPopUpMenuEventHandler AddNewIt
  • 异常堆栈跟踪不显示抛出异常的位置

    通常 当我抛出异常 捕获它并打印出堆栈跟踪时 我会看到抛出异常的调用 导致该异常的调用 导致该异常的调用that 依此类推回到整个程序的根 现在它只向我显示异常所在的调用caught 而不是它所在的地方thrown 我不明白是什么改变导致了
  • 如何以编程方式播放 16 位 pcm 数组 [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我有一个包含 16 位 pcm 值的短 数组 我希望能够在不添加任何标题 也不将任何文件保存到内存的情况下播放它 我知道我可能需要一个提供
  • 将下拉列表与字典绑定

    我将字典绑定到下拉列表 举例来说 我的字典中有以下项目 Test1 123 Test2 321 我希望下拉文本采用以下格式 Test1 Count 123 Test2 Count 321 我沿着以下路径走 但没有运气 MyDropDown
  • 全局使用和 .NET Standard 2.0

    我最近意识到我可以使用 C 10 功能文件范围的命名空间在 NET Standard 2 0 项目中也可以通过设置
  • C++ 将联合强制转换为其成员类型之一

    以下对我来说似乎完全符合逻辑 但不是有效的 C 联合不能隐式转换为其成员类型之一 有人知道为什么不这样做的充分理由吗 union u int i char c function f int i int main u v v i 6 f v
  • 有什么方法可以重载 C# 中的扩展方法吗?

    我有以下模型模式 public abstract class PARENTCLASS public class CHILD A CLASS PARENTCLASS public static class EXTENSION public s
  • 静态类与类的实例

    我有一个静态类 用于访问我的公共属性 整个应用程序的全局属性 和我在应用程序运行期间使用的方法 例如 我在静态类中设置了一些属性 并且在应用程序运行时我可以从属性中获取值 但我可以使用单例模式创建非静态类并以相同的方式使用它 问题 对于我的
  • 如何使用 Roslyn 通过扩展方法、静态类中的方法以及带有 ref/out 参数的方法来访问调用

    我正在致力于创建一个开源项目 用于创建 NET UML 序列图 该项目利用名为 js sequence diagrams 的 javascript 库 我不确定 Roslyn 是适合这项工作的工具 但我想我应该尝试一下 所以我整理了一些概念
  • 时间:2019-03-17 标签:c++fstream并发访问

    如果从不同的进程 线程同时访问文件会发生什么 据我所知 没有锁定文件的标准方法 只有操作系统特定的功能 就我而言 文件将被经常读取而很少写入 现在如果A打开一个文件进行读取 ifstream 并开始读取块 和B打开相同的文件进行写入 ofs
  • 如何在 C# 中获取 Json 数组?

    我有一个像这样的 Json 字符串 我想将它加载到 C 数组中 当我尝试这样做时 我收到异常 我的字符串 customerInformation customerId 123 CustomerName Age 39 Gender Male
  • 无法为 wsdl 文件创建服务引用

    I have wsdl文件和xsd我本地机器上的文件 我想在项目中添加服务引用 我没有网络服务 我只有wsdl file 我收到以下错误 The document was understood but it could not be pro
  • 如何使用 CSI.exe 脚本参数

    当你运行csi exe 安装了 Visual Studio 2015 update 2 您将得到以下语法 Microsoft R Visual C Interactive Compiler version 1 2 0 51106 Copyr
  • C 语言中的 Alpha 混合 2 RGBA 颜色[重复]

    这个问题在这里已经有答案了 可能的重复 如何快速进行阿尔法混合 https stackoverflow com questions 1102692 how to do alpha blend fast 对 2 个 RGBA 整数 颜色进行
  • Xamarin.Forms UWP 项目中标题栏和选项卡之间令人恼火的空白

    我几乎是新手Xamarin Forms我正在开发一个相当简单的跨平台应用程序 该应用程序在 Android 中显示得足够好 但在 UWP 中却出现了一个愚蠢的空白 该项目由一个 TabbedPage 组成 其中包含 4 个 Navigati
  • 这种尺寸对齐是如何工作的

    对于所提供的评论 我无法理解以下代码 这段代码的作用是什么 以及等效的代码是什么8 aligned segment size must be 4 aligned attr gt options ssize 3 Here ssize is o
  • 为什么表达式 a = a + b - ( b = a ) 在 C++ 中给出序列点警告?

    以下是测试代码 int main int a 3 int b 4 a a b b a cout lt lt a lt lt a lt lt lt lt b lt lt b lt lt n return 0 编译此命令会出现以下警告 gt g
  • C++ Boost ASIO 简单的周期性定时器?

    我想要一个非常简单的周期性计时器每 50 毫秒调用我的代码 我可以创建一个始终休眠 50 毫秒的线程 但这很痛苦 我可以开始研究用于制作计时器的 Linux API 但它不可移植 I d like使用升压 我只是不确定这是否可能 boost

随机推荐

  • Android:Log日志AS使用及Linux输出

    Android Studio中对应如下几种Log方法 1 Log v TAG 打印那些最为琐碎的 意义最小的日志信息 对应级别verbose 是Android 日志里面级别最低的一种 2 Log d TAG 打印一些调试信息 这些信息对你调
  • QT内存泄露问题

    原文链接 Qt浅谈之一 内存泄露 总结 乌托邦 CSDN博客 qt内存管理机制 关于堆栈不清楚的可以参考这篇文章 内存分配及堆与栈的区别 Keep Moving CSDN博客 在自己项目中 发现很多按键参数new之后并没有进行delete
  • vue面试题

    1 介绍一下vuex vuex是vue js应用的一个状态管理工具 state 用于保存我们应用的状态 2 v show与v if的区别和使用场景 区别 1 v show 只是简单的控制元素的 display 属性 而 v if 才是条件渲
  • 谷歌云|机密 GKE 节点可在计算优化的 C2D 虚拟机上使用

    机密 GKE 节点可用于计算优化的 C2D 虚拟机 许多公司已采用 Google Kubernetes Engine GKE 作为其应用程序基础架构中的关键组件 在某些情况下 使用容器和 Kubernetes 的优势可以超越传统架构 但迁移
  • linux中mysql启动服务命令(合集)

    linux的mysql启动服务命令 linux的mysql启动服务命令1 使用mysqld启动 关闭MySQL服务 mysqld是MySQL的守护进程 我们可以用mysqld来启动 关闭MySQL服务 关于mysqld MySQL 5 6官
  • You have not concluded your merge (MERGE_HEAD exists). Exiting because of unfinished merge.

    You have not concluded your merge MERGE HEAD exists Exiting because of unfinished merge git fetch all git reset hard ori
  • Select、Poll和Epoll

    看到一篇写得很不错的博文 有必要收藏一下 原文 https cloud tencent com developer article 1005481 提到select poll epoll相信大家都耳熟能详了 三个都是IO多路复用的机制 可以
  • 鸿蒙(二)基于小熊派实现LOT上云的智慧家居项目

    手把手教你利用鸿蒙OS实现智慧家居 LOT上云项目 一 前言 今天使用鸿蒙OS 做一个LOT上云的智慧家居项目 我们想实现的场景是这样的 云端WEB有一个控制界面 能够操控家房间里的灯和风扇 同时将房间里温度 湿度 光强实时显示出来 二 案
  • APUE学习的经验(引以为戒)

    前段时间在学习Linux 在没有感悟之前我是不敢把所得放到这里的 所以就一直没有新的文章 很惭愧啊 根据在网上搜集到的学习Linux的学习路线和自己当前对Linux的理解 我认为我可以学习APUE了 APUE 英文名应该是Advanced
  • mysql做生日日期字段的用到的类型_MySQL 日期类型函数及使用

    1 MySQL 数据库中有五种与日期时间有关的数据类型 各种日期数据类型所占空间如下图所示 2 datetime 与 date datetime 占用8字节 是占用空间最多的一种日期格式 它显示日期 同时也显示时间 5 5及以前的版本不支持
  • cmake命令之AUX_SOURCE_DIRECTORY 的案例

    AUX SOURCE DIRECTORY的命令形式如下 aux source directory
  • 16-MyCat

    一 Mycat概述 1 什么是Mycat 什么是Mycat Mycat是数据库中间件 所谓数据库中间件是连接Java应用程序和数据库中间的软件 为什么要用Mycat 遇到问题 Java与数据库的紧耦合 高访问量高并发对数据库的压力 读写请求
  • python selenium使用JS新建标签(new tab)与切换标签

    以下是通用操作 不建议用快捷键的方式新开tab 因为js是通用的 from selenium import webdriver driver webdriver Chrome 新建窗口 driver execute script windo
  • 【嵌入式开发基础】PL2303不支持win11及后续版本解决方法

    最近在使用PL2303这一块USB转串口后 在安装驱动时遇到如下问题 此PL2303驱动程序不支持WINDOWS 11及后续版本 请安装正确驱动程序 解决方法 下载旧版本的PL2303驱动然后安装替换 PL2303 Prolific Dri
  • C语言二分法查找算法

    二分查找算法 折半查找算法
  • echarts饼状图mysql_echarts饼状图位置设置

    ReactNative环境配置 参考链接 Windows系统安装React Native环境 windows下React Native Android 环境搭建 在Windows下搭建React Native Android开发环境 转载
  • Qt6.2.3 QWebEngineView 咋就默认无痕浏览模式了?

    最近项目从Qt5迁移到Qt6 有若干不兼容或者变动的地方 虽谈不上什么血泪史 但是一天内做了几十处的兼容性处理 好在项目不大 也是挺累人的 本文重点说说QWebEngineView 咋就默认变成无痕处理模式了 如何咱们如何取消无痕模式 自定
  • Linux安装node

    Linux安装node 一 下载准备 1 准备 2 下载wget 可以直接下载 也可以点击链接寻找下载 3 安装wget 二 安装 1 准备 2 下载 3 解压 4 配置 5 测试 一 下载准备 linxu安装node可以直接去官网下载 或
  • 用C++写一个ChatGPT

    要用 C 语言写一个 ChatGPT 需要执行以下步骤 了解 ChatGPT 是什么 ChatGPT 是一种自然语言生成模型 能够在聊天场景中生成人类语言的文本 安装需要的软件 需要安装 C 语言编译器 如 GCC 或者 Visual C
  • 【C++从0到1】C++入门(上篇)类入门篇

    c 入门必看 前言 一 命名空间 二 缺省函数 三 函数重载 3 1常见使用 3 2重载底层实现 3 3返回值不纳入重载原因 四 extren C 五 引用 5 1常见使用 5 2临时变量的作用 5 3引用返回常见错误 5 4指针与引用 六