C++入门基础篇

news2024/9/21 0:33:48

引言

  说到编程语言常常听到的就是C语言C++ Java 。C语言是面向过程的,C++是和Java是面向对象的,那么什么是面向对象呢?什么又是面向过程呢?C++是什么?封装、继承、多态是什么?且听我絮絮叨叨。

C++入门基础

1.命名空间

1.1 概念和作用

        在C语言中同一个作用域不能出现同名变量和函数,但在C++中可以因为C++提出了命名空间的概念,命名空间是一个单独的作用域。命名空间的目的是对标识符的名称进行本地化,以避免命名冲突或名字污染,namespace关键字的出现就是针对这种问题的。用语言描述描述这些东西太过于晦涩直接上代码!

命名空间的格式很简单只需要一个关键字namespace + 空间的名字 + {} 。那么如何访问命名空间中的内容呢?在获取命名空间中的变量时只需空间的名字加上"::"就可以访问命名空间的中的内容。

namespace zh
{
	//这一是叫zh的命名空间
	int i = 2;
	void fun()
	{
		printf("这是zh\n");
	}
}
namespace hh
{
	//这是叫hh的命名空间
	void fun()
	{
		printf("这是hh\n");
	}
	int i = 1;
}
int mian()
{
	zh::fun();
	hh::fun();
	printf("%d\n", zh::i);
	printf("%d\n", hh::i);
	return 0;
}

1.2 using关键字

通过using关键字可以引入命名空间中的变量,或是直接将命名空间引入。

namespace zl
{
	int c = 0;
}
using namespace hh;
using zl::c;
int main()
{
	printf("%d\n", c);
	fun();
	return 0;
}

2.C++的输入和输出

        在C语言中的输入和输出是借助printf和scanf进行操作的,但是在C++中不使用这两函数进行输入和输出而是使用cout和cin这两个对象需要包含头文件<iostream>,在C++在包含头文件时不需要在头文件后面加.h。这里也需要大家了解到是这使用cout和cin时我们需要引用std这个命名空间这是C++标准库,C++将标准库的定义和实现都放在这个名空间内。在日常的代码练习中建议直接展开这个命名空间,这样可以方便书写不展开的话如果想使用cout就需要在cout前面加上命名空间即std::cout。(这里只是简单的使用方法不涉及底层)

cout是标准输出流对象(控制台),cin是标准输入流对象(键盘),cout和cin的优势在于自动识别数据的类型。下面这两组代码的作用都是一样的你更愿意写哪种?

int main()
{
	int a = 9;
	//1
	printf("%d", a);
	scanf("%d", &a);
	//2
	cout << a;
	cin >> a;
	return 0;
}

3.缺省参数

3.1 概念

        缺省参数我愿称其为备胎,缺省参数的作用是在定义或者声明时可以给函数的参数一个缺省值,当调用函数时不进行传参这时在编译器就会将缺省值当做默认的参数进行传参。注意在声明和定义式不能同时给缺省值。

//void func(int i = 10);
void func(int i = 10)
{
	cout << i << endl;
}
int main()
{
	func();
	func(1);
	return 0;
}

 如果放开注释就会报错

 3.2 全缺省

全缺省的意思就是函数声明或者定义时所有的参数都给缺省值

void func1(int a = 1, int b = 2, int c = 3)
{
	cout << a << " " << b << " " << c << endl;
}
int main()
{
	func1();
	func1(8, 9, 10);
	return 0;
}
3.3 半缺省

 半缺省顾名思义就是给一半的缺省参数但是需要注意的是一半的缺省参数需要从右往左给。因为只有一部分的参数有缺省参数,另一部分没有缺省参数所以在传参的时候是从左往右传参的。

void func1(int a = 1, int b = 2, int c = 3)
{
	cout << a << " " << b << " " << c << endl;
}
void func2(int a, int b, int c = 100, int d = 900)
{
	cout << a << " " << b << " " << c <<" "<< d << endl;
}
int main()
{
	func2(1, 2);
	func2(100, 200);
	return 0;
}

4.函数重载

        如何构成函数的重载,当函数名相同返回值和形参的类型以及个数或者类型顺序不同时就可以构成函数的重载。直接上代码

//返回值类型不同和参数类型不同
int add(int a, int b)
{
	cout << "add(int a, int b)" << endl;
	return a + b;
}
double add(double a, double b)
{
	cout << "add(double a, double b)" << endl;
	return a + b;
}
//参数个数不同
int add(int a)
{
	cout << "add(int a)" << endl;
	return a;
}
//参数的顺序不同
void print(int a, char b)
{
	cout <<"print(int a, char b)"<< endl;
}
void print(char b, int a)
{
	cout <<"char b, int a"<< endl;
}
int main()
{
	add(1, 2);
	add(1.0, 2.0);

	add(100);

	print(1, 'c');
	print('c', 1);
}

 为什么C++支持函数重载呢?

因为在C++中在进行编译的时候C++会对函数名进行修饰通过参数的不同或者返回值的不同对函数名进行修饰给函数名添加特殊符号等,使得链接时每个函数名都对应着不同的函数。

但是C语言没有函数名修饰的机制,函数进行编译后就直接添加到符号表中,所以无法区分同名的不同函数。

5.引用

5.1 概念

引用是对一个已经初始化过的变量重新起一个别名,这个别名指向那个变量所在的位置,编译器不会为引用开辟空间,引用和被引用的变量共用一块空间。

int main()
{
	int a = 0;
	int& b = a;
	cout << a << endl;
	cout << b << endl;
	return 0;
}

5.2 引用的特殊性质 

1.引用定义时必须初始化。2.一个变量可以有多个引用。3.引用一个元素后就不能引用其他元素。

int main()
{
	int a = 0;
	int& b = a;
	int& i = a;
	int c = 9;
	b = c;//这段代码并不会改变b的引用而是将c的值付给b,又因为b是a的应用所以改变的是a的值
	cout <<"b = "<< b << " "<<"i = " << i << " " << "a = " << a << endl;
	return 0;
}

5.3 常引用

顾名思义常引用就是对常量进行引用,但是C++中规定不能对一个常量直接进行引用,常量即为不能被修改的量。这里就需要就需要引入新的知识点,权限的放大和缩小。

权限的放大:对于一个被const修饰的对象,是不能被绑定到一个非const的引用上,当一个非const的引用绑定到const修饰的对象上时,因为被const修饰的对象是不能被修改,但是非const修饰的引用是可以随意修改的,这就导致了权限的放大(不能修改->可以随意修改),这就导致了两个概念相悖。

权限的缩小:对于一个常量对象,是可以被绑定到一个const修饰的引用上的,因为常量对象不能被修改,const修饰的引用也不能被修改,原本的引用是可以随意的修改但是加上了const修饰就将其的权限进行了缩小,在C++中权限可以被缩小但是不能被放大。

int main()
{
	//将一个const修饰的对象进行权限的缩小
	const int a = 9;
	const int& c = a;
	//将一个变量的引用用const修饰,引用本身是可以随意修改的但是加上了const就不能修改了也是权限的缩小
	int b = 7;
	const int& z = b;
	b = 2;//但是b变量本身是可以修改的因为b没有被const修饰
	return 0;
}
5.4引用的使用

C语言和C++是极度追求效率的语言,引用就能极大的提升效率。为什么说引用可以提升效率呢?下面举两个例子:1.引用做函数的参数 2.引用做函数的返回值

1.引用做为函数的参数
int Add1(int& a1, int& b1)
{
	return a + b;
}
int Add2(int a2, int b2)
{
	return a + b;
}
int main()
{
	int a = 9;
	int b = 8;
	Add1(a, b);
	Add2(a, b);
	return 0;
}

 上面这两段代码功能都是一样,但效率上不同。引用作为函数的参数也是就说a1是a的一个别名也就说a1是没有开辟空间的,但Add2中a2在调用的时候是需要开辟一个临时新的空间用于存储形参这个过程是需要时间的。因为计算机的计算速度非常的快,所以这两个函数调用时效率上没有区别但是如果当在调用的时候进行大量的传参呢?比如对一亿个数据进行排序呢?这样差距就体现出来了。所以在C++中经常用到引用做参数。

2.引用做函数的返回值
int& Add(int a, int b)
{
	int c = a + b;
	return c;
}
const int& Add1(int a,int b)
{
    return a + b;
}
int main()
{
	int& ret = Add(1, 2);
	Add(3, 4);
	cout << "Add(1, 2) is :" << ret << endl;
	return 0;
}

注:函数的返回值不是直接进行返回而是先创建一个临时变量,将临时变量的值赋给接收函数返回值的变量。临时变量是具有常性的Add1函数中返回值是cosnt类型引用的返回值,为什么要加const是因为Add1返回的是一个临时的变量具有常性所用要用const进行修饰缩小权限。

所以上述代码的结果是什么?

上述代码的结果是随机值。因为:Add函数是引用做返回值,所以返回的是一个临时的变量这个临时变量,用了一个ret引用接收ret和这个临时变量共用一个空间。这函数的栈帧结束之后这个临时变量就销毁了,临时变量销毁了所以ret就没有指向的内容了,即便在调用了一次Add因为没有用ret接收所以,这段代码运行的结果是随机值。

 5.5 引用和指针的区别

指针和引用的区别是一道经典的C++面试题。

1.从内存的角度来说指针在创建的时候是需要创建空间存储地址的,但引用不需要引用就是给原本的空间起一个别名。

2.指针可以不进行初始化,但是引用必须进行初始化。

3.有多级指针但是没有多级引用。

4.指针可以随意改变指向,但是引用不可以。

5.在sizeof中含义不同,引用返回的是引用类型的大小,而指针在32位下(4个字节)和64位下(8个字节)返回值不同。

6.引用加1即被引用的对象进行加1,指针加一是指针向后偏移一个类型的长度。

7.访问实体的方式不一样,引用编译器自动处理,指针需要解引用。

8.指针会出现野指针和为空的情况,而引用不会所以引用更加安全。

6.内联函数

6.1概念

被inline修饰的函数被称为内联函数,内联函数也是用来提高效率的。内联函数会被调用的地方进行展开,展开的目的就是不创建函数的栈帧提高运行效率。

6.2特性

1.内联是一种以空间换时间的做法,在调用的地方直接将函数展开会使目标文件会变大。

2.内联只是对编译器的一种建议,编译器可以选择不采用。假设你将一个要递归多次的函数定义为内联函数那么编译器是不会对其进行展开的。

3.内联函数不能进行函数的定义和分离,因为内联函数在编译阶段是直接被展开的,如果定义和申明分离就会导致找不到函数的地址就会导致无法连接错误。

为了实现内联展开,编译器需要在编译时看到函数的完整定义。如果内联函数的定义和声明分离,编译器在看到声明时无法进行内联展开,因为它没有函数体的具体实现。

如果内联函数的定义和声明分离,并且定义仅在一个翻译单元中可见,那么其他翻译单元在链接时将无法找到该函数的实现,导致链接错误。

7.auto关键字

7.1概念

auto关键字是自动推导类型。当定义类型比较难拼写时可以实用auto(vector的迭代器)。

int main()
{
	auto a = 8;//这时auto就是整形
	auto b = 8.9;//这是auto就是double类型
	//这里打印一下a b 的类型
	cout << typeid(a).name() << endl;
	cout << typeid(b).name() << endl;
	return 0;
}

 7.2 特性

1.auto定义的时候必须初始化,因为如果不进行初始化编译器就无法推导auto定义的变量类型。

2. auto和auto*没有什么区别,但是auto引用必须加&

因为auto是可以自动推导类型的如果初始化变量的是一个地址那么auto就会初始化为个一指针类型,但引用不能省略&因为auto无法推导。

int main()
{
	int a = 0;
	auto b = &a;
	auto* c = &a;
	auto& v = a;
	cout << typeid(b).name() << endl;
	cout << typeid(c).name() << endl;
	cout << typeid(v).name() << endl;
	return 0;
}

 3.使用auto时不能进行一行有多个变量进行定义

4.auto不能用来定义函数的参数

void dunc(auto a)//因为这使用auto在编译时无法推导出变量的类型
{
	cout << "dunc" << endl;
}

5.auto不能用来定义数组(C++的规定)

8.范围for的使用和语法

如果想要遍历一个数组应该怎么写?

int main()
{
	//常规写法
	int a[] = { 1,2,4,5,6,7,8 };
	for (int i = 0; i < sizeof(a) / sizeof(a[0]); i++)
	{
		cout << a[i] << " ";
	}
	cout << endl;
	//范围for写法
	for (auto e : a)
	{
		cout << e << " ";
	}
	return 0;
}

9.空指针nullptr

 NULL是如何被定义的在C++98中NULL是一个宏被定义为(void*)指针或者0,所以这使用NULL指针时我们就会遇到麻烦。所以C++就引入了nullptr用来解决NULL的问题,相比于NULL来说nullptr更加安全。

void f(int)
{
cout<<"f(int)"<<endl;
}
void f(int*)
{
cout<<"f(int*)"<<endl;
}
int main()
{
f(0);
f(NULL);
f((int*)NULL);
return 0;
}

总结

        综上所述就是C++的一些入门知识点的讲解,这些知识点比较细碎不好理解但是这些知识点都是非常有用的在,某些特殊的场景下你会惊叹这样的语法设置非常巧妙。打个比方auto虽然看着确实方便但是好像也就一点点方便,举个栗子如果在STL容器中用来定义一些vector List这些容器的迭代器时你就感觉,auto太妙了。总之这些知识点之所以细碎是因为没有放到适合的场景下去体会,后面的博客我会带大家去好好体会其的妙用。

希望大佬们多多指点!也希望大家多多点赞、收藏、关注!

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

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

相关文章

fluent 旋转机械流场与声场仿真-学习笔记

这里写目录标题 1、动网格与滑移网格、运动参考系2、网格拓扑与共节点设置3、模型选择4、关于旋转壁面&#xff08;rotor_blade)的边界条件设置5、滑移网格瞬态计算时间步长设置6、风机声场仿真域![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/7855a595ee704c42a644…

【linux学习指南】Linux项目自动化构建工具 make /makefile进度条代码

文章目录 &#x1f4dd;前言&#x1f320; Makefile 格式&#x1f309;Makefile命令符号 &#x1f320;makefile/make基本原理&#x1f309;总和小案例 &#x1f320;进度条代码&#x1f6a9;总结 &#x1f4dd;前言 一个工程中的源文件多不技计数&#xff0c;其按其按类型、功…

某部门系统主机中病毒分析

一、安全巡检 正在写着代码&#xff0c;我的电脑火绒软件提示有内网攻击&#xff0c;关于一个古老的漏洞&#xff1a;“永恒之蓝”。瞬间来了兴趣&#xff0c;不会现在仍然有电脑中这病毒吧&#xff0c;打开绿盟安全管理平台。根据IP查询记录&#xff0c;果然有很多漏洞。 发…

《深入浅出WPF》读书笔记.11Template机制(上)

《深入浅出WPF》读书笔记.11Template机制(上) 背景 模板机制用于实现控件数据算法的内容与外观的解耦。 《深入浅出WPF》读书笔记.11Template机制(上) 模板机制 模板分类 数据外衣DataTemplate 常用场景 事件驱动和数据驱动的区别 示例代码 使用DataTemplate实现数据样式…

2024Mysql And Redis基础与进阶操作系列(1)作者——LJS[含MySQL的下载、安装、配置详解步骤及报错对应解决方法]

目录 1.数据库与数据库管理系统 1.1 数据库的相关概念 1.2 数据库与数据库管理系统的关系 1.3 常见的数据库简介 Oracle 1. 核心功能 2. 架构和组件 3. 数据存储和管理 4. 高可用性和性能优化 5. 安全性 6. 版本和产品 7. 工具和接口 SQL Server 1. 核心功能 2. 架构和组…

唯徳知识产权产权系统存在任意文件读取漏洞

漏洞描述 深圳市唯德科创信息有限公司&#xff08;以下简称&#xff1a;唯德&#xff09;于2014年在深圳成立&#xff0c;是专业提供企业、代理机构知识产权管理软件供应商&#xff0c;唯德凭借领先的技术实力和深厚的专利行业积累&#xff0c;产品自上市推广以来&#xff0c;…

一文讲懂Spring Event事件通知机制

目录 一 什么是spring event 二 怎么实现spring event 一 什么是spring event 我不会按照官方的解释来说什么是spring event&#xff0c;我只是按照自己的理解来解释&#xff0c;可能原理上会和官方有偏差&#xff0c;但是它的作用和功能就是这个&#xff0c;我更加偏向于从他…

CTK框架(三): 插件的安装

目录 1.方式1&#xff1a;使用ctk框架工厂&#xff0c;适用于调用普通的插件 1.1.步骤 1.2.实现 2.方法2&#xff1a;使用ctk框架启动器&#xff0c;适用于需要eventadmin时 2.1.实现 3.注意事项 1.方式1&#xff1a;使用ctk框架工厂&#xff0c;适用于调用普通的插件 1…

Linux服务器应急响应(下)

目录 介绍步骤 介绍 Linux alias命令用于设置指令的别名。 用户可利用alias&#xff0c;自定指令的别名。若仅输入alias&#xff0c;则可列出目前所有的别名设置。alias的效力仅及于该次登入的操作。若要每次登入是即自动设好别名&#xff0c;可在.profile或.cshrc中设定指令…

ggplot2 缩小的、带箭头的坐标轴 | R语言

1. 效果图 左侧为DimPlot2()效果图。 右侧为DimPlot()效果图&#xff0c;原图。 2. 代码 # DimPlot with 缩小的坐标轴 # # param scObject # param reduction # param group.by # param label # param raster # param legend.position # param ... # # return # expo…

OCC开发_变高箱梁全桥建模

概述 上一篇文章《OCC开发_箱梁梁体建模》中详细介绍了箱梁梁体建模的过程。但是&#xff0c;对于实际桥梁&#xff0c;截面可能存在高度、腹板厚度、顶底板厚度变化&#xff0c;全桥的结构中心线存在平曲线和竖曲线。针对实际情况&#xff0c;通过一个截面拉伸来实现全桥建模显…

长短期记忆神经网络-LSTM回归预测-MATLAB代码实现

一、LSTM简介&#xff08;代码获取&#xff1a;底部公众号&#xff09; 长短期记忆神经网络&#xff08;Long Short-Term Memory, LSTM&#xff09;是一种循环神经网络&#xff08;Recurrent Neural Network, RNN&#xff09;的变体。相比于传统的RNN&#xff0c;LSTM能够更好…

nvidia-smi 随机掉卡,error,禁用GSP功能

问题 NVIDIA 驱动中默认开启加载GPU卡的GSP功能&#xff0c;会随机导致在执行nvidia-smi命令的时候读取GPU卡为ERR状态&#xff0c;或者导致smi命令卡死&#xff1b; 如下图&#xff0c;以A800为例&#xff0c;Centos系统&#xff1b; 涉及到的包含以下型号的GPU卡&#xff…

C#中chart绘制曲线

官网资料&#xff1a;Chart 类 (System.Windows.Forms.DataVisualization.Charting) | Microsoft Learn 类的 Chart 两个重要属性是 Series 和 ChartAreas 属性&#xff0c;这两个属性都是集合属性。 Series集合属性存储Series对象&#xff0c;这些对象用于存储要显示的数据以…

2024年全新deepfacelive简易版-傻瓜式使用教程-采用AI换脸软件deepfacelive

# 2024年全新deepfacelive简易版-傻瓜式使用教程-采用AI换脸软件deepfacelive # 下载安装deepfacelive 官网下载&#xff1a; https://github.com/iperov/DeepFaceLive/ 下载好后放在至少有 30G以上的盘&#xff0c; # 启动使用-设置中文 解压好后&#xff0c;双击.bat批处理…

GPT系列之:GPT-1,GPT-2,GPT-3详细解读

一、GPT1 论文&#xff1a;Improving Language Understanding by Generative Pre-Training 链接&#xff1a;https://cdn.openai.com/research-covers/languageunsupervised/language_understanding_paper.pdf 启发点&#xff1a;生成loss和微调loss同时作用&#xff0c;让下…

java常用集合方法

目录 一、Iterator接口二、Iterable接口三、Collection接口四、Collection与Iterable关系 一、Iterator接口 Iterator 是一个集合迭代器接口&#xff0c;它提供了以下方法&#xff1a; 判断迭代器中是否还拥有元素&#xff0c;有则返回true&#xff0c;否则返回false boolean …

实验八 输入/输出流

实验目的及要求 目的&#xff1a;通过实验掌握java提供的输入/输出包中类的使用&#xff0c;特别是一些常用的类的方法的使用&#xff0c;运用流的概念实现对象的序列化。 要求&#xff1a; &#xff08;1&#xff09;编写程序使用BufferedReader和BufferedWriter对文件进行…

Java高级编程—网络编程(完整详解,包括UDP通信方式、TCP通信方式、TCP三次握手、TCP四次挥手,附有代码+案列)

文章目录 二十九.网络编程29.1 概述29.2 InetAddress29.3 UDP通信29.3.1 UDP通信发送数据29.3.2 UDP通信接收数据29.3.3 Test 29.4 UDP的三种通信方式29.4.1 单播29.4.2 组播29.4.3 广播 29.5 TCP通信29.6 TCP通信三次握手29.7 TCP通信四次挥手29.8 Test29.8.1 多次发送 二十九…

Java数据结构(九)——选择排序、堆排序

文章目录 选择排序算法介绍代码实现复杂度和稳定性 堆排序算法介绍代码实现复杂度和稳定性 选择排序 算法介绍 选择排序是一种简单直观的排序算法。它的工作原理是&#xff1a;首先在未排序序列中找到最小&#xff08;大&#xff09;元素&#xff0c;存放到排序序列的起始位置…