C++ 基础入门篇

news2024/9/27 9:26:39

文章目录

  • 命名空间
    • 输入与输出
      • 缺省参数
        • 函数重载
          • 引用和const引用
            • inline(内联函数)

命名空间

定义:命名空间需要用到namespace关键字,其后跟着命名空间的名字(自定义),再接着就是一对花括号,花括号里的内容可以是定义的变量,函数或者结构体

//对命名空间的定义
namespace fun
{
	int a = 1;
	int add(int left,int right)
	{
		return left + right;
	}
	struct Node
	{
		int data;
		int* next;
	}
}
int main()
{
	// ...
	return 0;
}

作用: 命名空间只能使用在全局域中,要知道,不同的域可以定义同一个变量,但在同一个域中不能定义同一个变量,防止在定义某个变量时与全局域产生冲突,空间命名在全局域中就起到了隔离的作用,其在全局域中形成一个命名空间域,该域与全局域互不干涉

若不使用命名空间,在编译时,系统就会出现下面的报错:

在这里插入图片描述
产生冲突时,命名空间就起到了作用:

在这里插入图片描述
可看到,rang成功打印,并未与在全局域中头文件中的rand产生冲突。在访问命名空间的成员时,需要用到" : : " 域作用限定操作符,在该操作符前添上自定义的命名空间名,在其后添上所要访问的成员即可。对于全局域中变量的访问,也可以用此操作符,在该操作符前的位置不添任何东西即可

命名空间中定义的变量,函数或结构体作用的范围是全局

在这里插入图片描述
可以看到在全局域中定义的函数,也可使用命名空间中定义的变量

  • 命名空间的嵌套定义

一个命名空间中可以有多个子命名空间:
在这里插入图片描述
编译查找一个变量/声明时,默认只会在局部和全局域查找,所以想要查找命名空间里的变量/声明的话,有三种方式:

  1. 指定访问命名空间
namespace fun
{
	int a = 10;
	int add(int x, int y)
	{
		return x + y;
	}
}
int main()
{
	printf("%d\n",fun::a); // 指定访问命名空间中的变量a
	return 0;
}
  1. 全部展开
namespace fun
{
	int a = 22;
	int b = 10;
}
using namespace fun; //将命名空间域全部展开成全局域
int main()
{
	printf("%d\n",a); // 展开之后命名空间中的变量可当成全局域使用
	printf("%d\n",b);
	return 0;
}

全部展开相当于将命名空间中的成员全部暴露在全局域中,这样的方式一般不适用于多人合作时使用,一般适用于个人做一些练习或简单程序时

  1. 部分展开
namespace fun
{
	int x = 1;
	int y = 0;
}
unsing fun::x; // 只对命名空间中的x进行展开
int main()
{
	printf("%d\n",x);
	printf("%d\n",fun::y);
	return 0;
}
  • C++标准库都放在一个叫std(stdandar)的命名空间中
  • 当项目工程中多文件中定义了同名的namespace,编译器会自动认为是同一个namespace,不会产生冲突

输入与输出

与C语言相比,C++的输入和输出会更加的灵活,来看下面的代码:

在这里插入图片描述

  • ”iostream“是标准输入,输出流的库,因为C++的标准库都被放在std的命名空间中,所以在访问库时须以访问命名空间的方式,来对库进行访问
  • std::cin 是istream类的对象,主要是面向窄字符的标准输入流
  • std::cout 是ostream类的对象,主要是面向窄字符的标准输出流
  • std::endl 是一个函数,相当于一个换行符加刷新缓冲区
  • << 是流的插入/输出运算符,>> 是流的提取/输入运算符

与C语言相比,C++的输入和输出不用一个指定格式或者多个格式,在写代码时,更加的方便

int main()
{
	int i = 10;
	char b = 'A';
	std::cout << i << std::endl << b << std::endl; // 不同类型的变量进行同时输出
	return 0;
}

缺省参数

概念:缺省参数是在声明或定义函数时,为函数设定一个缺省值(默认值),在调用函数时,若没有指定实参,则该函数就默认使用设定好的缺省值;若指定了实参,则使用实参的值

例:
在这里插入图片描述
可知,当第一次调用函数时,没有指定实参,a的值默认为缺省值4;当第二次调用函数时,指定了实参44,a的值为指定的实参

分类:

  • 全缺省:函数中有多个参数,每个参数都指定一个缺省值

在这里插入图片描述
调用全缺省参数时,传参只能从左往右传,不可跳跃传参

  • 半缺省:函数中有多个参数,参数中至少有一个以上设定有缺省值

在这里插入图片描述
设定缺省参数时,只能从右往左依次设定缺省值,不可跳跃设定

注:在设定缺省参数时,若函数的定义与声明是分离的,那么只能在函数声明时给定缺省值

函数重载

概念:C++支持在同一作用域中出现同名的函数,但要求函数的参数类型不同,或者函数的参数个数不同,这样的同名函数就被称作函数重载,函数重载弥补了C语言中出现的功能相同,但不能定义为同名函数的现象

分类:

  • 参数类型不同
    在这里插入图片描述
    可见,两次都调用了同名的add函数,但实质上这两个函数并不相同,只是功能上相同

  • 参数个数不同

在这里插入图片描述

  • 参数顺序不同
    在这里插入图片描述
    顺序不同,本质上其实也是类型不同
引用和const引用

概念:引用就是给变量取别名

定义:

int main()
{
	int i = 10;
	int& ri = i;
	return 0;
}

从上面的代码来看,ri就是 i 的别名, i 是被引用的变量,而 ri 是引用变量,编译器不会给引用变量另外开辟空间,而是与它所引用的变量公用同一个空间,由此可推出,ri 与 i 共用一个空间,若引用变量改变则被引用变量也会改变,反之,亦如此
在这里插入图片描述
引用的特性:

  • 定义引用变量时必须初始化
  • 一个变量可以有多个引用
  • 一个引用变量一旦引用了一个变量,就不可再引用其他变量了(C++的引用不能改变指向)
    在这里插入图片描述
    从上面的代码来看,将e赋值给了b,但是b的地址也不会改变,b已经有了引用变量a,便不会再引用其他变量

引用的使用方式:

  1. 作参数

在这里插入图片描述
我们知道,通常实现两个数交换的函数,实参传的是地址,需要用指针接收,然后再对指针进行解引用,而上面的代码,传的是值,分别用引用变量来进行接收,然后进行两个数的交换,体现了改变引用变量就会改变被引用变量这一个特点

  1. 指针的引用
typedef struct Node
{
	int data;
	struct Node* next;
}SL,*phead;

void SeqListInit(phead& plist,int x) 
			//这里的引用相当于 phead& plist = list
{
	SL* tmp = (SL*)malloc(sizeof(SL));
	if (tmp == NULL)
	{
		perror("malloc fail!");
		exit(-1);
	}
	tmp->data = x;
	tmp->next = NULL;
	plist = tmp;
}

int main()
{
	phead plist = NULL;//plist用来存放链表头结点的地址
	//对链表进行初始化
	SeqListInit(plist, 4);
	return 0;
}

代码结果:
在这里插入图片描述

我们知道,在对链表进行初始化时,想要改变一级指针的指向就需要取一级指针的地址,然后用二级指针来接收,通过对二级指针的解引用,就可改变一级指针的指向。但是使用C++的引用,就可以代替指针传参,也可以改变一级指针的指向,这样可较好的简化程序,避免指针混淆

  1. 作返回值
    用栈顶元素来举个例子:
    在这里插入图片描述
    系统在进行编译时,会有返回值的临时拷贝,并非直接将要返回的对象(st.arr[st.top-1])直接返回,所以在返回值的类型为int时,系统会为返回值开辟一个空间作为临时对象,来存储返回值,然后再返回临时对象(相当于返回的是要返回的对象的临时拷贝),所以在实行++StackTop(st)的操作时,其实是对临时对象进行++,而临时对象具有常性不能对其进行++的操作;而如果引用作为返回值,则相当于返回的是 st.arr[st.top-1] 的别名,即可以直接对别名进行修改,不会对其进行报错,系统在编译时也不会对其进行拷贝和开辟一个临时空间,

但是并不是任何场景都能用引用返回的,例如 :

在这里插入图片描述
调用fun()这个函数,在该函数中创建了临时变量 i ,而当调用结束,函数销毁时,该临时变量 i 也会被销毁,而对引用了 i 的别名进行修改,会造成越界访问,所以引用临时变量不可作为返回值

注:引用和指针是相辅相成的,二者皆不可替代,指针可以改变指向的对象,但引用改变不了,C++使用引用能简化程序,避免使用复杂的指针

const引用

概念:被const修饰的变量会受到权限,不可修改,有const的对象必须用const引用

int main()
{
	const int x = 10;
	const int& rx = x; //x受到const的修饰,所以rx也必须用const
	return 0;
}

在使用const的过程中需要注意:不可放大const对象的权限,但可以缩小没有const对象的权限,缩小了之后,被引用的对象可修改,引用对象不可修改

  • 不可放大权限

在这里插入图片描述
上述代码中的x受到了const的权限,当定义x的别名rx时,因为别名是不开辟空间的,与被引用对象共用同一块空间,x的空间受到限制,那么定义的x的别名rx也应受到限制,不可放大x空间的权限

  • 可以缩小权限
    在这里插入图片描述
    可看到,第二条指令被const修饰,缩小了rx的权限,所以rx不可修改,但是x并未受到权限的影响,所以x可修改

对const运用的延伸

int main()
{
	const int x = 10;
	int y = x;
	return 0;
}

上述代码是正确的,不存在权限的放大,const修饰的是x的这块空间,而将x赋给y是一种赋值拷贝,y也不与x共用同一块空间,所以不存在权限的放大

int main()
{
	const int a = 10;
	const int* p1 = &a;
	int* p2 = p1;
	return 0;
}

上述代码是错误的,这属于权限的放大,第二条指令中,const修饰的不是p1本身,修饰的是p1所指向的空间a不可被修改,且a受到了const的修饰,而将p1赋值给p2时,p2也应受到const的限制

int main()
{
	int b = 20;
	const int* p1 = &b;
	const int* p2 = p1;
	return 0;
}

上述代码正确,属于权限的缩小,变量b可读可写,将b的地址赋给p1后,p1又受到了const的权限,所以p2也应受到const的权限

int main()
{
	int c = 30;
	int* const p1 = &c;
	int* p2 = p1;
	return 0;
}

上述代码时正确的,不存在权限的放大,const修饰p1本身,并非其指向的空间c,p2 = p1相当于一个赋值拷贝,不影响p2对空间c的读写

指针和引用的关系

  1. 引用不开辟空间,指针需要开辟空间来存储变量的地址
  2. 引用必须初始化,而指针可不初始化
  3. 引用的指向一旦确定则不再修改,而指针的指向可随时修改
  4. 引用了直接访问指向的对象,而指针需解引用才可访问
  5. 引用的大小根据所指向的对象的类型决定,指针的大小在32位平台下是4字节,在64位平台下是8字节
  6. 引用的安全性较高于指针

注:引用在语法上是不开辟空间的,但在汇编底层中,其实跟指针是一样的,也需要开辟空间:

int main()
{
	int x = 10;
	int& rx = x;
	rx += 1;

	int* px = &x;
	*px += 1;
	return 0;
}

上述代码的汇编层如下:
在这里插入图片描述
可以看到,底层的汇编指令一模一样,所以引用的底层实现,与指针的实现是一样的

inline(内联函数)

概念:inline放在返回值的前面,用来修饰函数。编译器会对调用的inline函数进行展开,展开之后就不需要再建立函数栈帧,可提高程序的效率,inline函数的出现其实就是代替C语言中的宏,宏的使用直接在预处理阶段直接展开,可提高效率,但是宏的坑太多,所以就有了inline的出现

例如:

#include <iostream>
using std::cout;
using std::endl; 
inline int add(int x,int y)
{
	int ret = x + y;
	return ret;
}
int main()
{
	int sum = add(1,2);
	cout << sum << endl;
	return 0;
}

不展开的汇编指令如下:

在这里插入图片描述
不展开时,会有一条call指令,编译器会进入到call指令中,然后跳转到函数中,创建函数栈帧

展开的汇编指令如下:
在这里插入图片描述
显然展开后是没有call指令的,直接将实现函数的指令展开,也不会去建立函数栈帧

注:inline的使用对编译器来说只是一种建议,对函数的展开与否还是取决于编译器,一般来说,对于内联函数,若是短小的函数,编译器会对其进行展开,若函数过大,编译器就不会对其进行展开

在debug版本下,内联函数默认是不展开的(需要手动设置)

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

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

相关文章

气膜建筑在工业仓储厂房中的应用优势—轻空间

随着工业生产的快速发展&#xff0c;对仓储厂房的需求日益增长。气膜建筑作为一种新型的建筑形式&#xff0c;因其独特的优势在工业仓储领域逐渐受到青睐。以下是气膜建筑在工业仓储厂房中的主要应用优势。 快速建设与灵活布局 气膜建筑的一个显著优势是其建设速度快&#xff0…

免费分享:2021-2100中国多情景逐年干燥度模拟数据(附下载方法)

AI是表征一个地区干湿程度的指标&#xff0c;一般来说&#xff0c;根据AI分类可以概括地把区域分为湿润&#xff08;AI<1&#xff0c;相当于森林&#xff09;、半湿润&#xff08;AI在1-1.5&#xff0c;相当于森林草原&#xff09;、半干旱&#xff08;AI在1.5-4&#xff0c…

听,LLM在“说话“:智慧农场开启农业知识传播新范式

&#xff08; 于景鑫 国家农业信息化工程技术研究中心&#xff09;设施农业是现代农业的旗舰,集成了环境调控、水肥管理、植保防疫等多项先进技术。据统计,目前全国现代设施种植面积达到4000万亩&#xff0c;效率高、产出高、效益高的特点明显。北方地区每亩蔬菜日光温室年均纯…

十大免费录屏软件推荐:轻松录制高清视频教程

现在视频教程已经成为知识分享、教学演示以及内容创作的重要形式&#xff0c;无论是在线教育、游戏直播还是软件操作指导&#xff0c;高清、流畅的录屏软件都是我们不可获取的工具之一。 但目前市面上有很多录屏软件&#xff0c;哪款才是适合我们的呢&#xff1f;今天就给大家…

前端(vue3)和后端(django)的交互

vue3中&#xff1a; <template><div><h2>注册页面</h2><form submit.prevent"submitForm"><label for"username">用户名&#xff1a;</label><input type"text" id"username" v-model…

C++威力强大的助手 --- const

Welcome to 9ilks Code World (๑•́ ₃ •̀๑) 个人主页: 9ilk (๑•́ ₃ •̀๑) 文章专栏&#xff1a; C之旅 const是个奇妙且非比寻常的东西&#xff0c;博主从《Effective C》一书中认识到关于const更深层次的理解&#xff0c;写此博客进行巩固。 &#x…

无人机之运输的优势

无人机在进行运输任务时使用的是电力驱动&#xff0c;从而可以减少对环境的污染和碳排放&#xff0c;对于改善大气质量和减少碳足迹具有积极的意义。 无人机运输可以避免人为错误和事故的发生&#xff0c;通过预先设定的飞行路线&#xff0c;进行精确点投放。此外&#xff0c;还…

零基础小白备考PMP需要多长时间?

PMP考试在中国大陆&#xff0c;平均每三个月安排一次考试。报名缴费一般在考试前两个月&#xff0c;报完名后开始进入备考&#xff0c;所以基本上是2-3个月的时间。 PMP考试备考不是越久越好&#xff0c;把备考战线拉得太长 &#xff0c;我们的精力都是有限的&#xff0c;后期…

学习HTTP2中的HPACK算法

文章目录 HPACK动态表中的数据插入点两种基本数据类型 Integer String HPACK 专业术语&#xff1a; Header Field&#xff08;头部字段&#xff09;&#xff1a;指的是一个由name - value组成的键值对。名称和值都被视为不透明的字节序列。Dynamic Table&#xff08;动态表&a…

哪个软件可以识别字幕并生成文本?5款最佳工具分享

你是否曾在深夜&#xff0c;抱着手机或电脑&#xff0c;对着那些充满异国情调却无从下手的外语视频感到束手无策&#xff1f; 那些或激昂、或深情、或幽默的对话&#xff0c;因为语言的隔阂而变得遥不可及&#xff0c;让你的观看体验大打折扣。 别急&#xff0c;今天我来告诉你…

AI绘画进阶 ComfyUI 实战教程:轻松给图片添加文字,附工作流教程使用

大家好&#xff0c;我是设计师阿威 在AI绘画中书写文字一直是个老大难的问题&#xff0c;直到SDXL的出现&#xff0c;文字生成才迎来转机&#xff0c;可以在提示词中指定一些英文字符&#xff0c;不过也是经常出错&#xff0c;生成中文就更加不可求了。 本文介绍一种在图片中…

2018-Comment-网鼎杯复现,二次注入

进入靶场 发现只有一个发帖功能&#xff0c;尝试发帖 提交后要去登录&#xff0c;但这里提示了账号密码&#xff0c;但密码后三位不知&#xff0c;可以尝试暴力破解 bp抓包 假设后三位是数字&#xff0c;设置payload 爆破成功&#xff0c;后三位为666 登录成功 但除了发帖没有…

安泰电压放大器放大的是什么信号

电压放大器是一种广泛应用于电子设备中的放大器&#xff0c;它主要用于放大电压信号。电压信号是指以电压形式传输的信号&#xff0c;可以是来自于传感器、音频设备、无线通信设备等各种电子设备中的信号。 电压放大器的基本原理 电压放大器是一种电子设备&#xff0c;它可以将…

使用idea对spring全家桶的各种项目进行创建

目录 1. 简介2. spring2.1 简介2.2 创建 3. springmvc3.1 介绍3.2 创建 4. springboot4.1 简介4.2 创建&#xff08;仅仅就其中一种&#xff09; 5. 其他&#xff1a;maven6. 参考链接 1. 简介 因为总是分不清spring全家桶&#xff0c;所以就在这里进行一个总结。 2. spring …

Java毕业设计-基于SSM框架的大型商场会员管理系统项目实战(附源码+论文)

大家好&#xff01;我是程序猿老A&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f49e;当前专栏&#xff1a;Java毕业设计 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f380; Python毕业设计 &…

在手机中安装Fiddler CA证书后,完美解决Fiddler无法进行手机HTTPS请求抓包的难题!

Fiddler抓包的通用配置 关与fidder抓取手机包的配置方法就不多说了&#xff0c;网上有很多方式&#xff0c;配置方式如下图&#xff1a; 但是即使成功配置&#xff0c;在抓取手机中https包时也会出错&#xff0c;这个时候&#xff0c;我们就需要在手机中安装Fiddler的 CA证书!…

80.SAP ME - SAP ERP向SAP ME传输物料主数据的方法

目录 SAP ERP与ME传输物料的几种方式 1.自动传输物料到SAP ME 2.手动发送 2.1 BD10 发送物料 2.2 DRFOUT 执行数据复制 2.3 POIM 发送主数据 SAP ERP与ME传输物料的几种方式 1.自动传输物料到SAP ME 这是标准方法&#xff0c;需要全面的配置&#xff0c;当在ERP里修改物…

Powerdesigner连接mysql数据库,逆向工程生成ER图 (保姆级教程:下载->连接->配置)看这一篇就够了

一、下载powerdesigner 下载的教程请看如下链接&#xff0c;我太懒了&#xff0c;直接借鉴&#xff01; 把别大佬的博客搬过来了嘿嘿~我真聪明&#xff01;ㄟ( ▔, ▔ )ㄏ 操作到完成汉化就好&#xff01;&#xff01;第5步不看了&#xff0c;别按那个走&#xff0c;因为新手…

数据获取- 抓住股市脉搏,用Python轻松获取比亚迪股票数据!

Hey小伙伴们&#xff0c;今天给大家带来一个超级实用的项目教程——如何用Python和tushare库来获取比亚迪的股票数据&#xff01;&#x1f31f; &#x1f50d; 项目背景 股市是个充满机遇与挑战的地方&#xff0c;而获取实时准确的股票数据则是每个投资者的基础技能。今天&am…

2024华数杯全国大学生数学建模竞赛B题-VLSI电路单元的自动布局

超大规模集成电路(VLSI&#xff0c;VeryLarge Scale Integration)将大量电路单元集成于单一芯片。随着设计复杂度增加&#xff0c;如今开展VLSI设计已离不开电子设计自动化(EDA&#xff0c;Electronic DesignAutomation)工具的支持。EDA作为算法密集型产业&#xff0c;需要对数…