[C++] 由C语言过渡到C++的敲门砖

Kevin的技术博客.png



命名空间

在C/C++中,变量、函数和后⾯要学到的类都是⼤量存在的,这些变量、函数和类的名称将都存在于全
局作⽤域中,可能会导致很多冲突。使⽤命名空间的⽬的是对标识符的名称进⾏本地化,以避免命名
冲突或名字污染 。

在同一个工程中,不同文件中定义的同名namespace会被认为是同一个namespace,不会冲突。

嵌套

命名空间内可以嵌套命名空间,如示例代码:

namespace Kevin
{namespace star{string star = "Messi";}namespace sport{string sport = "Football";}
}

命名空间的使用

在使用时进行展开使用:

cout << Kevin::sport::sport << Kevin::star::star << endl;

• 指定命名空间访问,项⽬中推荐这种⽅式。
• using将命名空间中某个成员展开,项⽬中经常访问的不存在冲突的成员推荐这种⽅式。
• 展开命名空间中全部成员,项⽬不推荐,冲突⻛险很⼤,⽇常⼩练习程序为了⽅便推荐使⽤。


C++输⼊&输出

• 是InputOutputStream的缩写,是标准的输⼊、输出流库,定义了标准的输⼊、输
出对象。
• std::cin是istream类的对象,它主要⾯向窄字符(narrowcharacters(oftypechar))的标准输⼊流。
• std::cout是ostream类的对象,它主要⾯向窄字符的标准输出流。
• std::endl是⼀个函数,流插⼊输出时,相当于插⼊⼀个换⾏字符加刷新缓冲区。
• <<是流插⼊运算符,>>是流提取运算符。(C语⾔还⽤这两个运算符做位运算左移/右移)
• 使⽤C++输⼊输出更⽅便,不需要像printf/scanf输⼊输出时那样,需要⼿动指定格式,C++的输⼊
输出可以⾃动识别变量类型(本质是通过函数重载实现的,这个以后会讲到),其实最重要的是C++的流能更好的⽀持⾃定义类型对象的输⼊输出


缺省参数

缺省参数分为:全缺省,半缺省参数(默认参数)。

请注意:

  • C++规定半缺省参数必须从右往左依次连续缺省,不能间隔跳跃给缺省值 ;
  • 带缺省参数的函数调⽤,C++规定必须从左到右依次给实参,不能跳跃给实参;
  • 函数声明和定义分离时,缺省参数不能在函数声明和定义中同时出现,规定必须函数声明给缺省
    值。

全缺省

全缺省就是参数部分全部给缺省值

void Func1(int a = 10, int b = 20, int c = 30)
{cout << "a = " << a << endl;cout << "b = " << b << endl;cout << "c = " << c << endl << endl;
}

可以如下使用:

Func1();
Func1(1,2,3);

半缺省参数(默认参数)

半缺省就是部分形参给缺省值

void Func2(int a, int b = 10, int c = 20)
{cout << "a = " << a << endl;cout << "b = " << b << endl;cout << "c = " << c << endl << endl;
}

可以如下使用:

Func2(1);
Func2(1,2);
Func2(1,2,3);


函数重载

C++⽀持在同⼀作⽤域中出现同名函数,但是要求这些同名函数的形参不同,可以是参数个数不同或者
类型不同。

参数类型不同

样例如下:

// 1、参数类型不同
int Add(int left, int right)
{cout << "int Add(int left, int right)" << endl;return left + right;
} 
double Add(double left, double right)
{cout << "double Add(double left, double right)" << endl;return left + right;
} 

参数个数不同

样例如下:

// 2、参数个数不同
void f()
{cout << "f()" << endl;
} void f(int a)
{cout << "f(int a)" << endl;
} 

参数类型顺序不同

样例如下:

// 3、参数类型顺序不同
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;
}

不能构成函数重载的举例

返回值不同

当返回值不同的时候,我们在使用的时候无法识别出要使用哪一个函数,因为使用哦的时候仅仅是调用,不会显式的告诉编译器你要用哪个返回值的函数,所以返回值不同的函数不能构成重载。

// 返回值不同不能作为重载条件,因为调⽤时也⽆法区分
void fxx()
{}int fxx()
{return 0;
}

全缺省参数与无参函数

区别于构造函数,类外的全缺省参数函数与无参函数构成的函数重载无法正常调用,存在歧义。当调用时编译器不知道应该使用哪一个函数。

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


引用

给变量取别名,编译器不会为引用变量开辟内存空间,它和引用的变量共用一块内存空间。也就是说,通过引用可以直接改变引用的变量。(无法直接代替指针)

使用格式:

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

引用的特性

• 引⽤在定义时必须初始化
• ⼀个变量可以有多个引⽤
• 引⽤⼀旦引⽤⼀个实体,再不能引⽤其他实体

在定义时初始化

引用需要再定义的时候就进行初始化,如果执行以下代码会报错:

int& ra;
ra = a;

正确格式:

int& ra = a;

一个变量可以有多个引用

int& ra = a;
int& aa = a;
int& ba = a;

可以根据上述代码进行多个引用别名引用同一个变量,通过修改ra,aa,ba都可以改变a的值。

定义后不能改变引用实体

int& ra = a;
int& ra = b; //error

当已经在定义的时候引用一个实体变量后,在后续这个别名就不能再引用别的变量了。

为什么引用无法直接代替指针?

在链表中,节点就是指针,无法用指针替代。

我们使用链表的尾插进行讲解,代码如下:

#include <stdlib.h>typedef struct LTNode {int val;struct LTNode* next;
} LTNode;typedef struct LTNode* PNode;void ListPushBack(PNode** phead, int x) {// 动态分配内存给新节点PNode newnode = (PNode)malloc(sizeof(LTNode));if (newnode == NULL) {// 内存分配失败的处理return;}newnode->val = x;      // 设置新节点的值newnode->next = NULL;  // 新节点的next指针初始化为NULL// 如果链表为空,新节点即为头节点if (*phead == NULL) {*phead = newnode; // 将头指针指向新节点} else {// 如果链表不为空,找到链表的最后一个节点PNode current = *phead;while (current->next != NULL) {current = current->next;}// 将最后一个节点的next指针指向新节点current->next = newnode;}
}

为什么要用二级指针?

  1. 指针变量的值:指针变量存储的是另一个变量的内存地址。当你有一个指针PNode* p,p的值是另一个LTNode对象的地址。当解引用时:*p则代表着直接操作LTNode对象。
  2. 间接修改:如果你有一个指针的引用(即二级指针),比如PNode** pp,你可以修改*pp的值,即改变pp所指向的指针变量的值。这相当于间接修改了指针变量本身。因为我们要改变头指针的指向,所以用**p来接收头结点(修改一级指针的指向),然后再函数中就可以通过解引用进行修改头指针指向。而对于修改next指向本身是不用二级指针接收的。

当用C++风格修改后的函数:

void ListPushBack(PNode*& pheadRef, int x) {// 动态分配内存给新节点PNode newnode = (PNode)malloc(sizeof(LTNode));if (newnode == NULL) {// 内存分配失败的处理return;}newnode->val = x;newnode->next = NULL;// 如果链表为空,新节点即为头节点if (pheadRef == NULL) {pheadRef = newnode; // 使用引用直接修改头指针} else {// 如果链表不为空,找到链表的最后一个节点PNode current = pheadRef;while (current->next != NULL) {current = current->next;}// 将最后一个节点的next指针指向新节点current->next = newnode;}
}

当使用PNode*&的时候与int&类似,表示一个结构体指针的引用。在函数中直接通过修改phead的值就可以修改头结点的指向,而不需要像二级指针一样需要解引用才可以改变一级指针指向 。

引用返回值

例如想要改变栈顶元素:

int STTop(ST& rs)
{assert(rs.top > 0);return rs.a[rs.top - 1];
}int main()
{STTop(st1) = 3;
}

该代码运行会报错:

必须为左值元素(可修改,赋值变量)

原因

当该返回值为int时,返回的临时变量STTop(st1)为常量,常量无法修改。

解决措施

用引用来解决该问题。

当用引用做返回值,就是返回rs.a[rs.top - 1]的引用。此时当再用STTop(st1) = 3;修改栈顶数据即可完成。

const引用

代码书写可能会有以下错误:

const int a = 10;
int& ra = a; // error

当使用int&来接收const int类型的值时,对于int&来说相当于把权限放大了,而权限放大时不允许的。因为原来的a是一个不可修改的int常量,而如果要用int&接收的话,int&本身是要对所引用的对象进行修改等操作的,如此即违规了。

但是如下代码相反:

int a = 10;
const int& ra = a; // yes

原因如上述的相反结论,即缩小了权限,权限的缩小是被允许的。

常量的延伸

(表达式1 + 表达式2)在赋值时也会产生临时对象

  • 注意:临时对象具有常性!

如下:

const int a = 10;
int b = 20;int& rab = (a + b); // error

与上述类似:int&如果接受一个常量会将权限放大,不允许。

const int a = 10;
int b = 20;int rab = (a + b); // yes

但当使用一个整型变量接收的话会直接对临时对象进行拷贝,拷贝不涉及权限的放大缩小,仅仅是数据上的拷贝!
int&是为了取别名对引用对象进行操作,而拷贝只是进行数据的拷贝。

指针和引用的关系

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


inline

inline对于编译器⽽⾔只是⼀个建议 ,用inline修饰的函数也叫内联函数,编译的时候C++编译器会在调用的地方将函数内的代码全部展开,这样调用内联函数就不用寄哪里栈帧了,从而提高效率。

格式一般如下:

inline int Add(int x, int y)
{int ret = x + y;ret += 1;ret += 1;ret += 1;return ret;
}

注意:

  • vs编译器debug版本下⾯默认是不展开inline的,这样⽅便调试,debug版本想展开需要设置⼀下
    以下两个地⽅
  • inline不建议声明和定义分离到两个⽂件,分离会导致链接错误。因为inline被展开,就没有函数地
    址,链接时会出现报错。

内联函数比较于宏

宏的回顾

#define ADD(a, b) ((a) + (b))
// 为什么不能加分号?
// 为什么要加外⾯的括号?
// 为什么要加⾥⾯的括号?
  1. 为什么不能加分号?
  • 在调用宏的时候必须保证调用时写的与定义的宏函数格式一样,如果多加了分号的话那在调用的时候就会因为缺少分号而报错;
  1. 为什么要加外面的括号?
  • 例如在使用宏函数进行运算cout << 3 * ADD( 1 , 2 ) << endl;时就会因为运算符优先级的问题而计算错误。所以在定义宏函数的时候将括号写准确有利于后续程序的稳定。
  1. 为什么要加里面的分号?
  • 如果使用宏 ADD(a++, b),没有括号的情况下,宏会展开成 a++ + b,这将导致 a 被递增两次:一次是因为宏展开,另一次是因为 a++ 本身。但加上括号后,宏展开为 ((a)++) + b,这在大多数编译器中是不允许的,因为不允许对括号内的表达式进行递增操作,从而避免了这种错误。

nullptr

void f(int x)
{cout << "f(int x)" << endl;
} void f(int* ptr)
{cout << "f(int* ptr)" << endl;
}

C++中NULL可能被定义为字⾯常量0,或者C中被定义为⽆类型指针(void*)的常量。 由于在C++中NULL被定义成了0,所以例如:调⽤了f(int x),因此与程序的初衷相悖。f((void*)NULL);调⽤会报错。

其他关于C++的知识:
类和对象:构造、析构、拷贝构造

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

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

相关文章

Python基础-成年人判断(if条件语句联系)

注意输入的年龄需要转化为字符串 代码&#xff1a; print("欢迎来到游乐场&#xff1a;儿童免费&#xff0c;成人收费") age int(input("请输入你的年龄:")) if age>18:print("你已经成年&#xff0c;需要补票10元") # 四个空格缩进print…

使用ssh服务器管理远程主机

前言&#xff1a;本博客仅作记录学习使用&#xff0c;部分图片出自网络&#xff0c;如有侵犯您的权益&#xff0c;请联系删除 目录 一、配置网卡服务 1、配置网卡参数 2、创建网络会话 3、绑定两块网卡 二、远程控制服务 1、配置sshd服务 2、在Windows连接 3、安全密钥…

数据仓库哈哈

数据仓库 基本概念数据库&#xff08;database&#xff09;和数据仓库&#xff08;Data Warehouse&#xff09;的异同 整体架构分层架构方法论ER模型&#xff08;建模理论&#xff09;维度模型 何为分层第一层&#xff1a;数据源&#xff08;ODS ER模型&#xff09;设计要点日志…

Studying-代码随想录训练营day34| 62.不同路径、63.不同路径II、343.整数拆分、96.不同的二叉搜索树

第34天&#xff0c;动态规划part02&#xff0c;牢记五部曲步骤&#xff0c;编程语言&#xff1a;C 目录 62.不同路径 63.不同路径II 343.整数拆分 96.不同的二叉搜索树 总结 62.不同路径 文档讲解&#xff1a;代码随想录不同路径 视频讲解&#xff1a;手撕不同路径 题目…

源码编译构建LAMP(企业网站架构部署与优化)

部署LAMP平台 LAMV架构是目前成熟的企业网站应用模式之一&#xff0c;指的是协同工作的一整套系统和相关软件&#xff0c;能够提供动态Web站点服务及其应用开发环境。LAMP是一个缩写词&#xff0c;具体包 括 Linux操作系统&#xff0c;Apache网站服务器、MySQL数据库服务器、P…

【Python】基础语法体系:两种常用语句

个人主页&#xff1a;【&#x1f60a;个人主页】 系列专栏&#xff1a;【❤️Python】 文章目录 前言条件语句动态实例if语句if-else 语句if-elif-else 语句嵌套条件语句 循环语句for循环while循环 动态实例嵌套循环 前言 Python语句是构成Python程序的基本单元&#xff0c;用…

C++之goto陈述

关键字 goto用于控制程式执行的顺序&#xff0c;使程式直接跳到指定标签(lable) 的地方继续执行。 形式如下 标签可以是任意的识别字&#xff0c;后面接一个冒号。 举例如下 #include <iostream>int main() {goto label_one;label_one: {std::cout << "Lab…

【漏洞复现】29网课交单平台 SQL注入

声明&#xff1a;本文档或演示材料仅用于教育和教学目的。如果任何个人或组织利用本文档中的信息进行非法活动&#xff0c;将与本文档的作者或发布者无关。 一、漏洞描述 29网课交单平台是一个在线学习平台&#xff0c;用于帮助学生完成网络课程的学习任务。这个平台提供了包括…

Transformer中的编码器和解码器结构有什么不同?

Transformer背后的核心概念&#xff1a;注意力机制&#xff1b;编码器-解码器结构&#xff1b;多头注意力等&#xff1b; 例如&#xff1a;The cat sat on the mat&#xff1b; 1、嵌入&#xff1a; 首先&#xff0c;模型将输入序列中的每个单词嵌入到一个高维向量中表示&…

前端面试题34(在移动应用中,通用的实时传输协议)

在移动应用中&#xff0c;选择实时传输协议时通常会考虑几个关键因素&#xff1a;网络效率、功耗、实时性、跨平台兼容性以及数据类型&#xff08;如文本、图像、视频&#xff09;。以下是几种常用的实时传输协议及其在移动应用中的适用性&#xff1a; 1. WebSocket WebSocke…

AI转绘_animatediff-cli-prompt-travel

这个工具有两种主要模式&#xff1a;它可以直接通过提示创建视频&#xff0c;或者它可以对现有视频进行风格化。还有方法可以提高视频的分辨率。 正如工具名称所示&#xff0c;它的一个主要特点是"提示旅行"。这意味着你可以例如使用特定的提示用于前20帧&#xff0…

Github绑定自己的域名

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

算法复杂度

目录 1. 数据结构前言 1.1 数据结构 1.2 算法 2. 算法效率 2.1 复杂度的概念 3. 时间复杂度 3.1 大O的渐进表示法 3.2 时间复杂度计算示例: 3.2.1 示例1 3.2.2 示例2 3.2.3 示例3 3.2.4 示例4 3.2.6 示例6 4. 空间复杂度 4.1 空间复杂度计算示例 4.1.1 示例1 …

Nacos2.X 配置中心源码分析:客户端如何拉取配置、服务端配置发布客户端监听机制

文章目录 Nacos配置中心源码总流程图NacosClient源码分析获取配置注册监听器 NacosServer源码分析配置dump配置发布 Nacos配置中心源码 总流程图 Nacos2.1.0源码分析在线流程图 源码的版本为2.1.0 &#xff0c;并在配置了下面两个启动参数&#xff0c;一个表示单机启动&#…

Java面试八股之MySQL主从复制机制简述

MySQL主从复制机制简述 MySQL的主从复制机制是一种数据复制方案&#xff0c;用于在多个服务器之间同步数据。此机制允许从一个服务器&#xff08;主服务器&#xff09;到一个或多个其他服务器&#xff08;从服务器&#xff09;进行数据的复制&#xff0c;从而增强数据冗余、提…

Qt 音频编程实战项目

一Qt 音频基础知识 QT multimediaQMediaPlayer 类&#xff1a;媒体播放器&#xff0c;主要用于播放歌曲、网络收音 机等功能。QMediaPlaylist 类&#xff1a;专用于播放媒体内容的列表。 二 音频项目实战程序 //版本5.12.8 .proQT core gui QT multimedia greate…

@Slf4j idea标红Cannot resolve symbol ‘log‘

一、背景 时间久了没有应用idea,打开工程后项目 log 提示报红&#xff0c;未能解析&#xff0c;Cannot resolve symbol log &#xff0c;Slf4j 注解正常&#xff0c;应用的lombok插件。 检查lombok插件安装情况&#xff0c;发现未安装&#xff0c;重新安装重启idea后正常。 二…

Cesium自定义着色器构件三角面片【闪烁】问题,但是一移动视角就闪烁

问题&#xff1a;已知各个顶点的坐标信息、颜色和索引信息&#xff0c;并自定义绘制三角面片。 但是绘制的三角面片随着视角稍微改动就会出现闪烁现象&#xff01;&#xff01;&#xff01;why? Cesium数据类型的精度问题&#xff0c;例如下面为了获取能接收到高精度坐标信息…

系统架构师考点--信息系统基础知识

大家好。今天我们来总结一下信息系统基础知识的相关考点&#xff0c;每年都会考&#xff0c;一般是在上午场选择题中&#xff0c;占3分左右&#xff0c;其次下午场论文也有可能会出相关的考题。 一、信息系统概述 信息系统&#xff1a; 是由计算机硬件、网络和通信设备、计算…

selenium,在元素块下查找条件元素

def get_norms_ele_text(self):elementsself.get_norms_elements()locBy.CSS_SELECTOR,"div.sku-select-row-label"by loc[0] # 获取By类型&#xff0c;例如By.CSS_SELECTORvalue loc[1] # 获取具体的CSS选择器字符串&#xff0c;例如"div.sku-select-row-l…