【C++】基础入门(详解)

🌟 Hello,我是egoist2023!

🌍 种一棵树最好是十年前,其次是现在!

目录

输入&输出

缺省参数(默认参数)

函数重载

引用

概念及定义

特性及使用

const引用

与指针的关系

内联inline和nullptr

inline

nullptr


输入&输出

前文了解到本贾尼认为C语言是有缺陷的,想弥补其缺陷,最后搞出自己的一套C++体系。其实,C语言的scanf和printf函数是有缺陷且过于冗杂(每次都需要手动指定格式),是否能通过一种方式使输入输出更简便呢?针对此问题在C++中引入了输入&输出流

  • <iostream> (全称: Input Output Stream )是标准的输入、输出流库,定义了标准的输入、输出对象。
  • std::cin 是 istream 类的对象,它主要面向窄字符的标准输入。(C++标准库都封在std的命名空间中)
  • std::cout 是 ostream 类的对象,它主要面向窄字符的标准输出流
  • std::endl 是⼀个函数,流插入输出时,相当于插入一个换行字符加刷新缓冲区(简单看成C语言中的\n)。
  • <<是流插入运算符,>>是流提取运算符。(在C语言还充当左移/右移位运算符)。
  • 输入输出可以自动识别变量类型(本质是通过函数重载实现的),最重要的是 C++的流能更好的支持自定义类型对象的输入输出。
#include<iostream>
#include<stdio.h>int main()
{int a = 1;std::cout << a;printf("%d", a);return 0;
}
  • IO流涉及类和对象,运算符重载、继承等很多面向对象的知识,因此在此章节只介绍IO流的用法。
  • 在vs编译器中<iostream>间接包含了<stdio.h>,因此可以使用printf。
#include<iostream>int main()
{int a = 1;std::cout << a;printf("%d", a);return 0;
}

缺省参数(默认参数)

  • 缺省参数是声明或定义函数时为函数的参数指定一个缺省值。在调用该函数时,如果没有指定实参采用该形参的缺省值

  • 缺省参数分为全缺省(全部形参给缺省值)和半缺省参数(部分形参给缺省值)。
  • C++规定半缺省参数必须从左往右依次连续缺省,不能间隔给缺省值。(同理依次给实参)
  • 函数声明和定义分离时,缺省参数不能在函数声明和定义中同时出现,规定必须函数声明给缺省值。(这样做的目的是避免冲突,因为编译器在链接时会合成制表符,此时,声明和定义都有缺省值就会产生冲突)

  • 缺省参数的意义远不止如此,在之前的栈和队列章节中,栈的初始化中capacity默认开始为0。若一开始明确插入1000个数据时,初始化时直接开好,避免多次扩容损失效率。(没有传参时会采用缺省参数的值。)

函数重载

在C语言中若要实现Add函数(需要支持整形、浮点型相加)时,需要保证Add函数名字不冲突,为了解决这一困扰。在C++中,添加了函数重载这个概念,其要求这些同名函数的形参不同,可以是参数个数不同或者类型不同(不支持返回类型不同),呈现多态行为,使用更加方便。函数支持三种类型的重载。

函数重载是C++中实现多态性的一种重要方式,具有重要意义(增强了代码的可读性,函数的通用性和复用性),同时为之后的模板(函数重载的支持)、运算符重载做了铺垫。

参数类型不同

int Add(int x, int y)
{cout << "int Add(int x, int y)" << endl;return x + y;
}double Add(double x, double y)
{cout << "double Add(double x, double y)" << endl;return x + y;
}

参数个数不同

void f()
{cout << "f()" << endl;
}
void f(int a)
{cout << "f(int a)" << endl;
}

参数顺序不同

void f(int a, char b)
{cout << "f(int a,char b)" << endl;
}
void f(char b, int a)
{cout << "f(char b, int a)" << endl;
}

引用

概念及定义

引用是给已存在变量取一个别名,语法层面上编译器不会为其开辟内存空间, 它和引用的变量共用同一块内存空间。(实际底层实现上开辟了空间,是用一个指针指向其引用的变量)
通过调试可以知道:别名和引用的变量指向 共同占用一块空间
反汇编观察 底层:a和b各自开了一块空间,b通过指针ptr指向了变量a

特性及使用

引用在定义时 必须初始化
支持多次引用
引用一个实体,其别名再不能引用其他实体
  • 实践中,引用传参和引用做返回值中减少拷贝提高效率和改变引用对象时同时改变被引用对象。
  • 使用C++引用替代指针传参,目的是简化程序,避开复杂的指针。
  • 引用传参和引用作返回值在实践中经常用到,达到了减少拷贝提高效率(指针也可以减少拷贝)和改变引用对象的目的。(针对自定义类型更为明显)

在指针章节中要求交换两个变量,涉及到传址调用(形参改变实参)。同样,使用引用也可以达到此目的。

const引用

变量也有被const修饰的情况,此时对其进行引用会报错(权限被放大了),因此需要引入 const引用。

权限要点  -- >  权限可以平移或者缩小,但一定不能放大。

  • 引用一个const对象,必须用const引用。const引用也可以引用普通对象,因为对象的访问权限可以缩小,不能放大。

  • 需要注意的是 int& rb = a*3; double d = 12.34; int& rd = d 这种场景下需要使用const引用

这里涉及到类型转换,将double转换为int&为何需要使用const引用呢?

在类型转换中,会产生临时对象(也称未命名对象),这个对象具有常性,此时rb和rd都是引用这个临时变量,权限被放大了,因此会出现报错

  •  临时对象是编译器需要一个空间暂存表达式的求值结果时临时创建的一个未命名的对象。

与指针的关系

由上文可以发现引用与指针的部分功能是类似的,那为什么本贾尼还引入了引用这个语法呢?

引⽤和指针在实践中相辅相成,功能有重叠性,但是各有特点,互相不可替代。如:C++引⽤定义后不能改变指向,相反地指针可以改变指向(链表章节中指针定义的结构是不能用引用替代的)。

引用与指针的关系
引用指针
语法上不开空间要开空间存储变量地址
必须初始化非必须初始化
不能改变指向可以改变指向
可以直接访问指向对象需要借助*访问指向对象
引用结果为引用类型大小看32位/64位平台
\野指针和空指针问题

内联inline和nullptr

inline

inline修饰的函数叫做内联函数,编译时C++编译器会在调用的地方展开内联函数,这样调用内联函数就需要建立栈帧了,就可以提高效率。
这个功能是和C语言中的define是类似的,inline又有什么优势呢?
宏函数实现很复杂很容易出错的,且不方调试,C++设计了inline目的就是替代C的宏函数。

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

inline int Add(const int& x, const int& y)
{
    return x + y;
}

在实现Add函数中使用define宏定义时需要考虑各种因素,而使用inline则无需顾虑很多,让编译器决定是否展开此函数。

  • inline对于编译器是一个建议(选择性展开),适用频繁调用的短小函数,对于递归函数,代码相对多一些的函数,加上inline也会被编译器忽略。
  • inline不建议声明和定义分离到两个文件 ,分离会导致链接错误。因为inline被展开,就没有函数地址,链接时会出现报错(不能合成制表符)。
  • vs编译器 debug版本下面默认是不展开inline的,因此需要设置下。

nullptr

引入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*) 的常量。但都不可避免的会遇到一些麻烦。
nullptr(关键字)是⼀种特殊类型的字面量,它可以转换成任意其他类型的指针类型。使用 nullptr定义空指针可以避免类型转换 的问题。(nullptr只能被隐式地转换为指针类型,而不能被转换为整数类型)
在此代码中,本想通过f(NULL)调用函数f(int x),但运行后发现调用的f(int x)函数,与设计此程序是相违反的。

若NULL为无类型指针(void*)呢?运行后会报错,这是因为2个函数重载中没有一个能转换所有参数类型。
#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(NULL);//调用f(int x)f(nullptr);//调用f(int* ptr)f((void*)0);//errreturn 0;
}

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

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

相关文章

【Elasticsearch】runtime_mappings搜索请求中定义运行时字段

在 Elasticsearch 中&#xff0c;在搜索请求中定义运行时字段&#xff08;Runtime Fields&#xff09;是一种强大的功能&#xff0c;允许用户在查询时动态添加和计算字段&#xff0c;而无需预先在索引映射中定义这些字段。这种方式提供了极大的灵活性&#xff0c;尤其是在处理动…

数学建模基础训练-1:概念解析

文章目录 数学建模基础训练-1&#xff1a;概念解析问题一&#xff1a;如何找到“概念”&#xff1f;问题二&#xff1a;如何全面理解概念的基础含义&#xff1f;问题三&#xff1a;如何深刻理解概念并作出创新点发掘&#xff1f;实际举例问题一 :研究并给出寒假开学某大学返校交…

【Linux基础】Linux下常用的系统命令

文章目录 一、前言二、系统监控和进程管理指令2.1 ps命令2.2 top命令2.3 kill命令2.4 shutdown命令 三、文件和目录管理指令3.1 cd命令3.2 ls命令3.3 mkdir命令3.4 cat 命令3.5 cp命令3.6 mv命令3.7 rm命令3.8 chmod命令3.9 ln命令3.10 pwd命令 四、文件查找和文本处理指令4.1 …

mysql读写分离与proxysql的结合

上一篇文章介绍了mysql如何设置成主从复制模式&#xff0c;而主从复制的目的&#xff0c;是为了读写分离。 读写分离&#xff0c;拿spring boot项目来说&#xff0c;可以有2种方式&#xff1a; 1&#xff09;设置2个数据源&#xff0c;读和写分开使用 2&#xff09;使用中间件…

【Git版本控制器】:第一弹——Git初识,Git安装,创建本地仓库,初始化本地仓库,配置config用户名,邮箱信息

&#x1f381;个人主页&#xff1a;我们的五年 &#x1f50d;系列专栏&#xff1a;Linux网络编程 &#x1f337;追光的人&#xff0c;终会万丈光芒 &#x1f389;欢迎大家点赞&#x1f44d;评论&#x1f4dd;收藏⭐文章 ​ 相关笔记&#xff1a; https://blog.csdn.net/dj…

双轴伺服电机驱动控制器AGV、AMR专用双伺服电机驱动控制器解决方案

工业机器人数控机床XY机械手双轴机器人堆垛机专用双轴伺服电机驱动控制器48V 14ARMS带有STO功能&#xff0c;隔离高压CAN/RS485/USB通讯支持编码器和霍尔输入 双伺服电机驱动控制器TMCM2611功能介绍 集成2个伺服电机的控制和驱动于一体供电电压48V&#xff0c;驱动电流14A RM…

flutter本地推送 flutter_local_notifications的使用记录

flutter_local_notifications 效果 安卓配置(AndroidManifest.xml) <uses-permission android:name"com.android.alarm.permission.SET_ALARM"/> <uses-permission android:name"android.permission.SCHEDULE_EXACT_ALARM" /> <us…

宝塔和docker的区别

宝塔面板 vs Docker&#xff1a;区别、场景与互补使用指南 eepseek回答宝塔和docker的区别 好的&#xff0c;我现在需要回答用户关于宝塔面板和Docker之间的区别的问题。首先&#xff0c;我需要明确这两个工具各自的定义、功能以及它们适用的场景&#xff0c;这样才能准确比较…

【算法专场】哈希表

目录 前言 哈希表 1. 两数之和 - 力扣&#xff08;LeetCode&#xff09; 算法分析 算法代码 面试题 01.02. 判定是否互为字符重排 ​编辑算法分析 算法代码 217. 存在重复元素 算法分析 算法代码 219. 存在重复元素 II 算法分析 算法代码 解法二 算法代码 算法…

PHP本地商家卡券管理系统

本地商家卡券管理系统 —— 引领智慧消费新时代 本地商家卡券管理系统&#xff0c;是基于ThinkPHPUni-appuView尖端技术匠心打造的一款微信小程序&#xff0c;它彻底颠覆了传统优惠方式&#xff0c;开创了多商家联合发行优惠卡、折扣券的全新模式&#xff0c;发卡类型灵活多变…

Kafka分区管理大师指南:扩容、均衡、迁移与限流全解析

#作者&#xff1a;孙德新 文章目录 分区分配操作(kafka-reassign-partitions.sh)1.1 分区扩容、数据均衡、迁移(kafka-reassign-partitions.sh)1.2、修改topic分区partition的副本数&#xff08;扩缩容副本&#xff09;1.3、Partition Reassign场景限流1.4、节点内副本移动到不…

极狐GitLab 17.8 正式发布,多项 DevOps 重点功能解读【二】

GitLab 是一个全球知名的一体化 DevOps 平台&#xff0c;很多人都通过私有化部署 GitLab 来进行源代码托管。极狐GitLab 是 GitLab 在中国的发行版&#xff0c;专门为中国程序员服务。可以一键式部署极狐GitLab。 学习极狐GitLab 的相关资料&#xff1a; 极狐GitLab 官网极狐…

AWTK-WEB 快速入门(4) - JS Http 应用程序

XMLHttpRequest 改变了 Web 应用程序与服务器交换数据的方式&#xff0c;fetch 是 XMLHttpRequest 继任者&#xff0c;具有更简洁的语法和更好的 Promise 集成。本文介绍一下如何使用 JS 语言开发 AWTK-WEB 应用程序&#xff0c;并用 fetch 访问远程数据。 用 AWTK Designer 新…

LabVIEW外腔二极管激光器稳频实验

本项目利用LabVIEW软件开发了一个用于外腔二极管激光器稳频实验的系统。系统能够实现激光器频率的稳定控制和实时监测&#xff0c;为激光实验提供了重要支持。 项目背景&#xff1a; 系统解决了外腔二极管激光器频率不稳定的问题&#xff0c;以满足对激光器频率稳定性要求较高…

计算机毕业设计--基于深度学习技术(Yolov11、v8、v7、v5)算法的高效人脸检测模型设计与实现(含Github代码+Web端在线体验界面)

基于深度学习技术&#xff08;Yolov11、v8、v7、v5&#xff09;算法的高效人脸检测模型 Yolo算法应用之《基于Yolo的花卉识别算法模型设计》&#xff0c;请参考这篇CSDN作品&#x1f447; 计算机毕业设计–基于深度学习技术&#xff08;Yolov11、v8、v7、v5&#xff09;算法的…

国家队出手!DeepSeek上线国家超算互联网平台!

目前,国家超算互联网平台已推出 DeepSeek – R1 模型的 1.5B、7B、8B、14B 版本,后续还会在近期更新 32B、70B 等版本。 DeepSeek太火爆了!在这个春节档,直接成了全民热议的话题。 DeepSeek也毫无悬念地干到了全球增速最快的AI应用。这几天,国内的云计算厂家都在支持Dee…

Android和DLT日志系统

1 Linux Android日志系统 1.1 内核logger机制 drivers/staging/android/logger.c static size_t logger_offset( struct logger_log *log, size_t n) { return n & (log->size - 1); } 写的off存在logger_log中&#xff08;即内核内存buffer&#xff09;&am…

安卓手游内存call综合工具/内部call/安卓注入call/数据分析(类人猿学院)

进程分析注入综合工具总界面 模块分析函数分析遍历 函数分析 so汇编分析 汇编call植入器&#xff0c;支持模拟器x86 x64 和手机arm64指令全平台 防ce搜索数据功能 全国首套发布&#xff0c;阿凡老师学院最好的安卓内存逆向老师&#xff0c;几乎行业最强的&#xff0c;有兴趣可以…

Kotlin 扩展

Kotlin 扩展 引言 Kotlin 作为一种现代编程语言,以其简洁、安全、互操作性强等特点,在 Android 开发领域占据了重要地位。其中,Kotlin 扩展(Extensions)是其一项非常实用的特性,它允许开发者以简洁的方式对类、对象或属性进行扩展。本文将详细介绍 Kotlin 扩展的概念、…

通过例子学 rust 个人精简版 1-1

1-1 Hello World fn main() {println!("Hello World!");// 动手试一试println!("Im a Rustacean!"); }Hello World! Im a Rustacean!要点1 &#xff1a;println 自带换行符 注释 fn main() {let x 5 /* 90 */ 5;println!("Is x 10 or 100? x …