【c++之于c的优化】

news2024/9/22 11:39:29

目录:

  • 前言
  • 关键字
  • 一、命名空间
      • 1.什么是命名空间
      • 2.如何使用命名空间
      • 3.如何自己创建命名空间
      • 4.为什么要使用命名空间
      • 5.命名空间起别名
      • 6.匿名命名空间
  • 二、缺省参数
      • 定义
      • 缺省参数类型
      • 注意事项
  • 三、函数重载
      • 定义
      • 函数重载的三种方式
      • 操作系统的区分方式
  • 四、引用
      • 定义
      • 引用特性
      • 使用场景
      • 引用和指针的比较
  • 总结

前言

打怪升级:第31天
在这里插入图片描述

C语言是模块化和结构化的语言,适合处理较小规模的程序。对于复杂的问题。需要高度抽象和建模时,C语言则不适用。
为了解决软件危机,我们需要一些可以解决新的问题的语言;
20世纪80年代, 计算机界提出了OOP(object oriented programming:面向对象)思想,支持面向对象的程序设计语言应运而生。
1982年,Bjarne Stroustrup博士在C语言的基础上添加了命名空间、缺省参数等特性,并且引入并扩充了面向对象的概念,
通过对C语言知识的不断扩充,内容越来越多,之后便把它独立出来当做一种新的语言,同时为了表明和C语言的渊源,就把它命名为c++。

c++语言之父:Bjarne Stroustrup博士
在这里插入图片描述

下面,就让我们一起打开c++的大门, 领略这份跨越40年光阴,经久不衰的语言的魅力。

关键字

首先是对关键字的补充,C语言有32个关键字,c++有63个,几乎是C语言的两倍。
这里我们只做了解。
在这里插入图片描述

一、命名空间

#include<iostream>
using namespace std;

int main()
{

	return 0;
}

我想上面的代码框架大家都不会陌生,这,就是c++梦开始的地方。
我们先来了解每个语句的含义:

  1. #include :包含头文件 ;
  2. using namespace std; :使用标准命名空间std;
  3. 主函数体。

第一部分的头文件包含与宏定义等这些预处理指令和第三部分的主函数都是C语言同样拥有的,那么这第二句的命名空间又是什么呢,
我想在学校学习的时候大多数老师都是一句“我们在写c++的时候,前面两条语句是必须带上的,大家记住就好。”但是很少有老师会为我们详细介绍,我们只知道如果不写会出错,但是为什么会出错呢?

1.什么是命名空间

故名思路,命名空间是用来存放“名字”的空间,我们可以在命名空间中进行对变量的声明、类的声明、函数的声明和实现、并且还可以嵌套其他的命名空间等。
c++为了和c语言区分开,也为了正确的使用命名空间,规定头文件不写后缀.h;
因此,当我们使用**<iostream.h>的时候,相当于在c中调用库函数,使用的是全局命名空间**;(vs等编译器已经没有这个头文件了)
当我们使用**< iostream >的时候,由于该头文件没有定义全局命名空间,而是把函数声明放到了标准命名空间std**中,所以我们要使用标准函数库中的函数或对象都要使用std来限定。(std是命名空间的标识符)。

在这里插入图片描述

2.如何使用命名空间

使用命名空间有三种方法:

  1. 加命名空间名称及作用域限定符;
  2. 使用using,将命名空间中成员引入;
  3. 使用using namespace,将命名空间引入。

下面我们来一一介绍:

1.加命名空间名称及作用域限定符
在这里插入图片描述

2.使用using引入命名空间成员
在这里插入图片描述

  1. 使用using namespace 引入命名空间
    在这里插入图片描述

3.如何自己创建命名空间

创建命名空间需要用到关键字:namespace
语法:namespace 命名空间名 { }
eg:在这里插入图片描述

#include<iostream>

using namespace std;

namespace panda
{
	int num = 2023;  //  变量

	void Print()   //  函数
	{
		cout << "Create namespace panda" << endl;
	}

	namespace kz   //  嵌套命名空间
	{
		class person{}; 
	}
}

int main()
{
	panda::Print();

	cout << endl << panda::num << endl;

	return 0;
}

4.为什么要使用命名空间

使用命名空间是为了防止命名冲突(名字相同),在C语言中,如果两个变量名字相同那就一定会出错,因为编译器无法对它们进行区分;
但是在c++中,我们可以将它们放到不同的命名空间中,使用不同的变量就在对应的命名空间中寻找即可。
在这里插入图片描述
在这里插入图片描述

5.命名空间起别名

#include<iostream>

using namespace std;

namespace panda
{
	int num = 2023;  //  变量

	void Print()   //  函数
	{
		cout << "Create namespace panda" << endl;
	}
}

namespace p = panda;   //  命名空间取别名

int main()
{
	panda::Print();

	cout << endl << p::num << endl;

	return 0;
}

6.匿名命名空间

#include<iostream>

using namespace std;

namespace          //   匿名命名空间
{
	int num = 2023;  //  变量

	void Print()   //  函数
	{
		cout << "Create namespace panda" << endl;
	}
}


int main()
{
	Print();

	cout << endl << num << endl;

	return 0;
}

运行示例:
在这里插入图片描述

使用匿名命名空间时不需要使用命名空间名进行限定,此时如果它外面没有嵌套其他命名空间的话,使用操作就和全局函数类似,
但是如果全局变量中存在同名变量,就需要再次进行区分,
区分方法 -> ::变量名
功能:访问全局区的变量。
eg:
在这里插入图片描述


二、缺省参数

定义

缺省参数是指在声明或定义一个函数时为它赋予一个缺省值,调用函数时,若没有传入实参,形参就会使用该缺省值,否则就使用实参。

示例:

#include<iostream>
using namespace std;

void MultiAdd(int a = 0, int b = 20, int c = 30)
{
	cout << "a + b + c = " << a + b + c << endl;
}

int main()
{
	MultiAdd();
	MultiAdd(100);
	MultiAdd(1000, 200, 300);
	return 0;
}

运行实例:
在这里插入图片描述

缺省参数在开辟空间时比较常用,我们既可以提前设置数组大小,也可以使用默认值。

#include<iostream>
using namespace std;

int* GetArr(int size = 10)  //  默认大小为10
{
	int* tmpp = (int*)malloc(sizeof(int) * size);
	if (tmpp == NULL)
	{
		perror("GetMem::malloc");
		exit(1);
	}

	return tmpp;
}

int main()
{
	int* pa = GetArr();  //  使用默认大小
	int* pb = GetArr(1000); //  设置开辟数组大小为1000
	return 0;
}

缺省参数类型

类型分两种:全缺省和半缺省

举个栗子:

              //  全缺省:每个形参都有缺省值
void MultiAdd(int a = 0, int b = 20, int c = 30)
{
	cout << "a + b + c = " << a + b + c << endl;
}

			// 半缺省:有的形参有缺省值,有的没有,并非必须是一半一半
void MultiAdd(int a, int b = 20, int c = 30) // 注意:缺省值必须从右往左赋予
{
	cout << "a + b + c = " << a + b + c << endl;
}
			//  都没有缺省值就是普通函数

注意事项

  1. 缺省参数必须从右往左赋予,不能间隔着给;
  2. 缺省参数不能在函数定义和声明时同时赋值;
  3. 分文件编写函数时,只有在头文件中声明函数时可以写上缺省值,不能在定义时给定;
  4. 缺省值必须是常量或全局变量;
  5. C语言不支持缺省值;

示例3
在这里插入图片描述
总而言之:分文件编写时,缺省值不能在函数定义处赋予。


三、函数重载

在自然语言中,很多词语都不止拥有一个意思,我们可以根据不同的语境需要来进行代入;
eg:学校的电脑坏了,计算机老师一会儿就修理好了。(bushi)
今天张三犯了错,罗老师说一会儿就去修理他。
上面的“修理”这个词语就被重载了。

定义

函数重载:函数的特殊形式,c++允许在同一个作用域下声明多个同名函数,这些函数的参数列表需要有所差异(参数个数、参数类型、参数顺序),常用来处理功能类似,参数类型不同的问题。

举个栗子:

#include<iostream>
using namespace std;

int Add(int a, int b)
{
	cout << "Add(int , int);" << endl;
	return a + b;
}

double Add(double a, double b)
{
	cout << "Add(double , double);" << endl;
	return a + b;
}

int main()
{
	cout << Add(10, 20) << endl;
	cout << Add(10.0, 20.5) << endl;
	return 0;
}

在这里插入图片描述

函数重载的三种方式

函数重载的前提:同一作用域下,函数名相同的函数。

  1. 参数个数不同;
  2. 参数类型不同;
  3. 参数类型顺序不同。
//  1. 参数个数不同
int Add(int a)
{
	return a + 100;
}

int Add(int a, int b)
{
	return a + b;
}


//  2.参数类型不同
int Add(int a, int b)
{
	return a + b;
}

double Add(double a, double b)
{
	return a + b;
}


//  3.参数类型顺序不同
double Add(int a, double b)
{
	return a + b;
}

double Add(double a, int b)
{
	return a + b;
}

操作系统的区分方式

不同编译器下对函数名的修饰各不相同,
由于vs中对函数修饰的规则比较复杂,我们下面在Linux中来查看对函数名的修饰。
Linux对函数名的修饰:
C语言:C语言不支持函数重载,因此不会出现同名函数的问题,所以并不需要再进行修饰。
c++:编译器通过参数列表的不同来区分重载的函数,
规则: _Z + 函数名长度 + 函数名 + 参数列表中参数类型的简写
至于为什么前面是 _z 而不是 _panda ,我想很可能是当时制定命名规则的大佬们没有见过可爱的大熊猫喽~。

示例
C语言:
这里是引用> c++:
在这里插入图片描述在这里插入图片描述

Windows下对函数名的修饰规则,感兴趣的朋友可以看一看。
这里是引用


四、引用

定义

引用不是新定义一个变量,而是给一个已存在的变量起别名,此时编译器不会给引用变量分配内存,而是和它引用的对象共用同一块内存空间。
一个变量可以有一个或多个别名,例如:张三,我们有时也会称之为张某或法外狂徒。

语法:类型 & 引用变量名 = 引用实体;
在这里插入图片描述

引用特性

  1. 引用类型必须和引用实体的类型相同;
  2. 一个变量可以有多个引用;
  3. 引用必须初始化;
  4. 引用创建出来后就不能再成为其他实体的引用;
  5. 常引用。
void TestRef()
{
   int a = 10;
   // int& ra;   // 该条语句编译时会出错
   int& ra = a;
   int& rra = a;
   printf("%p %p %p\n", &a, &ra, &rra);  
}

常引用:常量的引用必须使用const修饰。
示例:

	void TestConstRef()
	{
		const int a = 10;
		//int& ra = a;   // 该语句编译时会出错,a为常量
		const int& ra = a;
		// int& b = 10; // 该语句编译时会出错,b为常量
		const int& b = 10;

		double d = 12.34;
		//int& rd = d; // 该语句编译时会出错,类型不同
		double& rd = d;

		const int& id = d;    //**如果一定要这样写,编译器会给id重新开辟一块空间。**
		cout << d << endl << id << endl;
		d = 20.05;
		cout << d << endl << id << endl;
		cout << "-----------------------------------" << endl;
		cout << &d << endl << &id << endl;
	}

运行实例:

使用场景

  1. 当参数传递
  2. 返回值
  3. 传值和传引用的比较
    当参数传递
void Swap(int x, int y)
{
	cout << "Swap(int, int);" << endl;
	int z = x;
	x = y;
	y = z;
}

void _Swap(int& x, int& y)
{
	cout << "Swap(int&, int&);" << endl;
	int z = x;
	x = y;
	y = z;
}

void test03()
{
	int a = 20;
	int b = 30;
	Swap(a, b);
	cout << "a = " << a << ", b = " << b << endl << endl;
	_Swap (a, b);
	cout << "a = " << a << ", b = " << b << endl;
}

在这里插入图片描述

作为返回值

int& Add(int x, int y)
{
	int z = x + y;
	return z;    //  返回的引用不可用
}


void test04()
{
	int& cnt = Add(10, 20);
	cout << "cnt = " << cnt << endl;
}

在这里插入图片描述

传值和传引用的比较
1.做参数

#include <time.h>
struct A { int a[100000]; };
void TestFunc1(A a) {}
void TestFunc2(A& a) {}
void TestRefAndValue()
{
	A a;
	// 以值作为函数参数
	size_t begin1 = clock();
	for (size_t i = 0; i < 10000; ++i)
		TestFunc1(a);
	size_t end1 = clock();
	// 以引用作为函数参数
	size_t begin2 = clock();
	for (size_t i = 0; i < 10000; ++i)
		TestFunc2(a);
	size_t end2 = clock();
	// 分别计算两个函数运行结束后的时间
	cout << "TestFunc1(A)-time:" << end1 - begin1 << endl;
	cout << "TestFunc2(A&)-time:" << end2 - begin2 << endl;
}

结果分析:

2.做返回值

结果同上。

引用和指针的比较

在语法上,引用就是一个别名,没有独立的空间,和引用实体共用一块空间。
在底层实现上,实际上是有空间的,因为引用实际上是由指针实现的。

int main()
{
	int a = 10;
	int& ra = a;
	ra = 20;
	int* pa = &a;
	*pa = 20;
	return 0;
}

引用和指针反汇编代码完全一样。
这里是引用
引用和指针的比较:

  1. 引用在定义上和引用实体共用一份空间,指针则开辟一份空间存放地址;
  2. 引用必须初始化,指针则不需要;
  3. 没有空引用,有空指针;
  4. 引用在初始化时确定了引用对象后,不能再引用其他变量,指针可以随时指向同类型的变量;
  5. 不存在多级引用,存在多级指针;
  6. 可以直接通过引用对象访问引用实体,指针则需要使用解引用(*);
  7. sizeof(引用对象)的值是引用实体的类型的值,sizeof(指针)的值就是一个地址的大小,与类型无关;
  8. 引用自加是引用实体的值加1,指针自加是向后偏移一个类型的大小;
  9. 引用比指针使用起来相对更安全。

总结

以上就是今天讲解的c++中命名空间、缺省参数、函数重载、以及引用的全部内容,如果有什么疑问或者建议都可以在评论区留言,感谢大家对在这里插入图片描述的支持。

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

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

相关文章

【4-网络八股扩展】北京大学TensorFlow2.0

课程地址&#xff1a;【北京大学】Tensorflow2.0_哔哩哔哩_bilibiliPython3.7和TensorFlow2.1六讲&#xff1a;神经网络计算&#xff1a;神经网络的计算过程&#xff0c;搭建第一个神经网络模型神经网络优化&#xff1a;神经网络的优化方法&#xff0c;掌握学习率、激活函数、损…

【LeetCode每日一题】【2023/1/24】1828. 统计一个圆中点的数目

文章目录1828. 统计一个圆中点的数目方法1&#xff1a;枚举1828. 统计一个圆中点的数目 LeetCode: 1828. 统计一个圆中点的数目 中等\color{#FFB800}{中等}中等 给你一个数组 points &#xff0c;其中 points[i] [x_i, y_i] &#xff0c;表示第 i 个点在二维平面上的坐标。多…

【算法面试】队列算法笔试面试全解(金三银四面试专栏启动)

&#x1f4eb;作者简介&#xff1a;小明java问道之路&#xff0c;专注于研究 Java/ Liunx内核/ C及汇编/计算机底层原理/源码&#xff0c;就职于大型金融公司后端高级工程师&#xff0c;擅长交易领域的高安全/可用/并发/性能的架构设计与演进、系统优化与稳定性建设。 &#x1…

02_gpio子系统

总结 驱动程序还想控制gpio 可以不用读写寄存器 直觉用gpio子系统开发的接口就能用了 轻松做输入输出 获取当前值 详细介绍 用设备树里的节点 gpio1 介绍 imx6ull.dtsi gpio1 记录了控制器相关的寄存器基地址 gpio1: gpio209c000 {compatible "fsl,imx6ul-gpio"…

三、利用迁移学习进行模型微调(Datawhale组队学习)

文章目录安装配置环境准备图像分类数据集迁移学习微调训练图像分类模型导入环境图像预处理载入图像分类数据集建立类别和索引号之间映射关系定义数据加载器查看一个batch的图像和标注可视化一个batch的图像和标注模型的构建与测试可视化常见的迁移学习训练方式训练配置模型训练…

过完2022,依然记得仰望星空

&#x1f57a;作者&#xff1a;一名普普通通的双非大二学生迷茫的启明星&#x1f383;专栏&#xff1a;《数据库》《C语言从0到1专栏》《数据结构》《C语言杂谈》目录 ​编辑 一.2022之初 二.2022年中 三.2022年末 四.展望2023 一.2022之初 想起一年前这个时候&#xff0c…

07_plantform平台总线

总结 /sys/bus/plantform 平台总线其实就是继承 06_自己创建xbus总线 有了更多的玩法 和自己创建的xbus总线一样 平台总线也有dev和drv 需要这两个进行匹配之后 进行porbe调用 plantform_device 结构体中直觉继承了 struc device lantform_driver 继承了driver 详细介绍 plan…

树(基础部分)

章节目录&#xff1a;一、二叉树1.1 为什么要使用树&#xff1f;1.2 树的常用术语1.3 二叉树概念1.4 二叉树应用二、顺序存储二叉树2.1 概述2.2 基本应用三、线索化二叉树3.1 问题引出3.2 概述3.3 基本应用四、结束语一、二叉树 1.1 为什么要使用树&#xff1f; 数组存储方式&…

MP-2平面烟雾气体传感器介绍

MP-2平面烟雾气体传感器简介MP-2烟雾检测气体传感器采用多层厚膜制造工艺&#xff0c;在微型Al2O3陶瓷基片的两面分别制作加热器和金属氧化物半导体气敏层&#xff0c;封装在金属壳体内。当环境空气中有被检测气体存在时传感器电导率发生变化&#xff0c;该气体的浓度越高&…

【数据库概论】3.1 SQL简述、数据定义和索引

第三章 关系数据库标准语言SQL 目录第三章 关系数据库标准语言SQL3.1 SQL概述3.1.1 产生与发展3.1.2 SQL的特点3.1.3 SQL的基本概念3.2 数据库实例3.3 数据定义3.3.1 模式的定义和删除3.2.2基本表的定义、删除和修改1.常见数据类型2.定义基本表3.修改基本表4.删除基本表5.模式和…

英语学习打卡day3

2023.1.22 1.mariner n.水手 2.formation n.队形;组成;形成 n.形状;形式样式;表格 the formation of landscapes Keep the formation 保持队形 The chairs were arranged in the form of circle. fill in the form 填写表格 formal adj.正式的inform 通知deform 变形uniform 统…

06_平台总线匹配规则,自己搭建总线xbus

总结 bus_register() 自己创建平台总线 /sys/bux/xxx device_register() 对平台总线加入dev /sys/bus/xxx/dev driver_register() 对平台总线加入drv /sys/bus/xxx/drv 两个相匹配的时候 直接调用drv->probe 函数 进行基本的class_create() device_create()等 创建设备文件…

TryHackMe-红队-07_武器化

Weaponization 了解并探索常见的红队武器化技术。您将学习如何使用业内常见的方法来构建自定义有效负载&#xff0c;以获得初始访问权限。 什么是武器化 武器化是网络杀伤链模式的第二阶段。在此阶段&#xff0c;攻击者使用可交付的有效负载&#xff08;如word文档&#xff…

七、python-PySpark篇(黑马程序猿-python学习记录)

1. pyspark定义 2. 下载 点击右下角版本 点击解释器设置 点击号 搜索pyspark 选择pyspark 勾选选项 在输入框中输入 -i https://pypi.tuna.tsinghua.edu.cn/simple 点击安装软件包 提示正在安装 等一两分钟就能安装完毕 3. 获取PySpark版本号 # 导包 from pyspark import Spar…

树,二叉树的认识

1.树概念及结构 1.1树的概念 注意&#xff1a;树形结构中&#xff0c;子树之间不能有交集&#xff0c;否则就不是树形结构 1.2 树的相关概念 1.3 树的表示 树结构相对线性表就比较复杂了&#xff0c;要存储表示起来就比较麻烦了&#xff0c;既然保存值域&#xff0c;也要保存…

(18)go-micro微服务ELK介绍

文章目录一 什么是ELK二 Beats的六种工具三 ELK系统的特点四 ELKbeats系统架构五 ELK优点六 最后一 什么是ELK ELK是三个[开源软件]的缩写&#xff0c;分别表示&#xff1a;Elasticsearch , Logstash, Kibana , 它们都是开源软件&#xff0c;新增了一个Beats。 Elasticsearch …

几种觉排序优劣

冒泡排序 比较相邻的元素。如果第一个比第二个大&#xff0c;就交换他们两个。 对每一对相邻元素做同样的工作&#xff0c;从开始第一对到结尾的最后一对。在这一点&#xff0c;最后的元素应该会是最大的数。 针对所有的元素重复以上的步骤&#xff0c;除了最后一个。 持…

23. 异常处理机制

1. 异常 即便 python 程序的语法是正确的&#xff0c;在运行它的时候&#xff0c;也有可能发生错误。运行期检测到的错误被称为异常。 # int不能与str相加, 触发异常 print(22) # 0 不能作为除数, 触发异常 print(1/0) # sum未定义, 触发异常 print(num)异常以不同的类型出现…

【JavaSE专栏4】关键字、标识符和命名规范

作者主页&#xff1a;Designer 小郑 作者简介&#xff1a;Java全栈软件工程师一枚&#xff0c;来自浙江宁波&#xff0c;负责开发管理公司OA项目&#xff0c;专注软件前后端开发&#xff08;Vue、SpringBoot和微信小程序&#xff09;、系统定制、远程技术指导。CSDN学院、蓝桥云…

k8s部署elk+filebeat。springCloud集成elk+filebeat+kafka+zipkin实现多个服务日志链路追踪聚合到es

一、目的 如今2023了&#xff0c;大多数javaweb架构都是springboot微服务&#xff0c;一个前端功能请求后台可能是多个不同的服务共同协做完成的。例如用户下单功能&#xff0c;js转发到后台网关gateway服务&#xff0c;然后到鉴权spring-sercurity服务&#xff0c;然后到业务…