C++入门的基础

幸福比傲慢更容易蒙住人的眼睛。 ——大仲马


C++入门

  • 1、属于C++的关键字
    • 1、1、C++从何而来
    • 1、2、C++关键字(C++98)
  • 2、命名空间
    • 2、1、命名空间的定义
    • 2、2、命名空间使用
  • 3、C++输入和输出
  • 4、缺省参数
    • 4、1、缺省参数概念
    • 4、2、缺省参数分类
  • 5、函数重载
    • 5、1、函数重载概念
  • 6、引用
    • 6、1、引用概念
    • 6、2、引用特性
    • 6、3、常引用
    • 6、4、使用场景
    • 6、5、传值、传引用效率比较
    • 6、6、引用和指针的区别
  • 7、内联函数
    • 7、1、概念
    • 7、2、特性
    • 7、3、inline细节
  • 8、auto关键字(C++11)
    • 8、1、auto介绍
    • 8、2、auto使用规则

1、属于C++的关键字

1、1、C++从何而来

为什么会出现C++呢?为什么C++的关键字和C语言相对比起来,有着不少的增加?
其实想要搞明白为什么会出现这种状况,首先要明白的是C++是祖师爷用C语言的过程中,饱受C语言中一些限制的诟病,在C语言的基础上增加的一个更牛的系统。在这里插入图片描述
Bjarne Stroustrup就是他创建的C++。
所以,对于学习过C语言的人来说,C++是一款不可多得的好用的语言。在基础之上为我们解决一些C语言不能够很好处理的问题,给我们节约时间,拥有更多的库,不再像C语言那样,还需要我们去造轮子。

1、2、C++关键字(C++98)

在这个版本中,总计是63个关键字,而C语言的关键字是32个,有了很大的提升。相对于C来说,提升了很多,也更方便了。
在这里插入图片描述

2、命名空间

为什么要有命名空间的这一术语?因为在C/C++中,变量,函数以及类都是大量存在的,这些都将存储于全局作用域,那么就可能会引起冲突。使用命名空间,就可以将标识符的名称本地化,从而避免命名冲突,而运用命名空间来解决问题的关键字就是namespace。

#include <stdio.h>
#include <stdlib.h>
int rand = 10;
// C语言没办法解决类似这样的命名冲突问题,所以C++提出了namespace来解决
int main()
{printf("%d\n", rand);
return 0;
}
// 编译后后报错:error C2365: “rand”: 重定义;以前的定义是“函数”

这就是很好的证明,C++之中namespace的便捷。

2、1、命名空间的定义

定义命名空间,需要使用namespace关键字,后面跟上的是命名空间的名字,然后街上一对{},在{}之中即为命名空间的成员。

// hehe是命名空间的名字,一般开发中是用项目名字做命名空间名。
// 我们上课用的是bit,大家下去以后自己练习用自己名字缩写即可,如张三:zs
// 1. 正常的命名空间定义
namespace hehe
{// 命名空间中可以定义变量/函数/类型int rand = 10;int Add(int left, int right){return left + right;}struct Node{struct Node* next;int val;};
}
//2. 命名空间可以嵌套
// test.cpp
namespace N1
{
int a;
int b;
int Add(int left, int right){return left + right;}
namespace N2{int c;int d;int Sub(int left, int right){return left - right;}}
}
//3. 同一个工程中允许存在多个相同名称的命名空间,编译器最后会合成同一个命名空间中。
// ps:一个工程中的test.h和上面test.cpp中两个N1会被合并成一个
// test.h
namespace N1
{
int Mul(int left, int right){return left * right;}
}

注意:一个命名空间就定义了一个新的作用域,命名空间中的所有内容都局限于该命名空间中。

2、2、命名空间使用

那么有了命名空间,该如何去使用不同作用域的成员呢?

namespace bit
{// 命名空间中可以定义变量/函数/类型int a = 0;int b = 1;int Add(int left, int right){return left + right;}struct Node{struct Node* next;int val;};
}
int main()
{// 编译报错:error C2065: “a”: 未声明的标识符printf("%d\n", a);
return 0;
}

那我们该怎么去找到这里的a呢?
命名空间的三种方法:
1、在使用前在上空间名称以及作用域限定符

int main()
{printf("%d\n", N::a);return 0;    
}

2、使用using将命名空间中的某个成员引入

using N::b;
int main()
{printf("%d\n", N::a);printf("%d\n", b);return 0;    
}

3、使用using namespace+命名空间 引用

using namespce N;
int main()
{printf("%d\n", N::a);printf("%d\n", b);Add(10, 20);return 0;    
}

通常而言,第三种在大型的组合团队中不要使用,因为标准库就全部暴露出来了,如果我们定义跟库重名的类型/对象/函数,就存在冲突问题。但是对于正常的人来说,写一些正常的程序,还是建议使用第三种的,不仅方便,还能理解到命名空间关键字的意义。

3、C++输入和输出

对于C来说的“hello world ”是我们学习的第一句话,那么关于C++来说,我们该怎么去让他在屏幕上显示出来呢?

#include<iostream>
// std是C++标准库的命名空间名,C++将标准库的定义实现都放到这个命名空间中
using namespace std;
int main()
{
cout<<"Hello world!!!"<<endl;
return 0;
}

说明:
1、 使用cout标准输出对象(控制台)和cin标准输入对象(键盘)时,必须包含< iostream >头文件
以及按命名空间使用方法使用std。
2. cout和cin是全局的流对象,endl是特殊的C++符号,表示换行输出,他们都包含在包含<
iostream >头文件中。
3. <<是流插入运算符,>>是流提取运算符。
4. 使用C++输入输出更方便,不需要像printf/scanf输入输出时那样,需要手动控制格式。
C++的输入输出可以自动识别变量类型。
5. 实际上cout和cin分别是ostream和istream类型的对象,>>和<<也涉及运算符重载等知识,
这些知识我们我们后续才会学习,所以我们这里只是简单学习他们的使用。
注意: 早期标准库将所有功能在全局域中实现,声明在.h后缀的头文件中,使用时只需包含对应头文件即可,后来将其实现在std命名空间下,为了和C头文件区分,也为了正确使用命名空间,规定C++头文件不带.h;旧编译器(vc 6.0)中还支持<iostream.h>格式,后续编译器已不支持,因此推荐使用+std的方式。

4、缺省参数

4、1、缺省参数概念

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

void Func(int a = 0)
{cout<<a<<endl;
}
int main()
{Func();     // 没有传参时,使用参数的默认值Func(10);   // 传参时,使用指定的实参
return 0;
}

4、2、缺省参数分类

全缺省参数

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

半缺省参数

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

注意:
1、半缺省参数不是指只有一半,而是必须从左往右依次来给出,不能间隔。
2、缺省参数不能再函数声明和定义中同时出现。

//a.hvoid Func(int a = 10);// a.cppvoid Func(int a = 20){}// 注意:如果生命与定义位置同时出现,恰巧两个位置提供的值不同,那编译器就无法确定到底该
用那个缺省值。

3、缺省值必须是常量或全局变量
4、C语言不支持(编译器不支持)

5、函数重载

在现实世界,一个词常常有着不同含义,我们可以同上下问之间的关系来判断词的真正含义,即使该词重载了。
重载从词语上的意思来说,从我的感觉来说,也可以看作是,重复的载入
以前有一个笑话,国有两个体育项目大家根本不用看,也不用担心。一个是乒乓球,一个是男足。前者是“谁也赢不了!”,后者是“谁也赢不了!

5、1、函数重载概念

函数重载:是函数的一种特殊情况,C++允许在同一作用域中声明几个功能类似的同名函数,这些类型的形参列表(参数个数 或 类型 或 类型顺序不同)

#include<iostream>
using namespace std;
// 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;
}
int main()
{Add(10, 20);Add(10.1, 20.2);f();f(10);f(10, 'a');f('a', 10);return 0;
}

6、引用

6、1、引用概念

引用不是创建一个新的变量,而是给已经存在的变量取别名,变量和变量的别名共同使用一块内存空间。
引用相当于给别人起外号,如果本人做了什么,或者说是别名做了什么,都是改变同一个人。
比如:李逵你吃过了吗,李逵吃过了,那黑旋风一定也是吃过了。
类型& 引用变量名(对象名)=引用实体

void TestRef()
{int a = 10;int& ra = a;//<====定义引用类型printf("%p\n", &a);printf("%p\n", &ra);
}

注意:引用类型必须是和实体是同种类型的

6、2、引用特性

1、引用并不能在定义的时候不初始化。
2、一个变量可以有多个引用
3、引用一旦引用一个实体,再也不能引用其他实体。

void TestRef()
{int a = 10;// int& ra;   // 该条语句编译时会出错int& ra = a;int& rra = a;printf("%p %p %p\n", &a, &ra, &rra);  
}

6、3、常引用

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; // 该语句编译时会出错,类型不同const int& rd = d;
}

6、4、使用场景

1、做参数

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; // 该语句编译时会出错,类型不同const int& rd = d;
}

2、做返回值

int& Count()
{static int n = 0;n++;// ...return n;
}

下面代码中,输出的结果是什么呢?

int& Add(int a, int b)
{int c = a + b;return c;
}
int main()
{int& ret = Add(1, 2);Add(3, 4);cout << "Add(1, 2) is :"<< ret <<endl;return 0;
}

在这里插入图片描述

6、5、传值、传引用效率比较

以值作为参数或者返回值类型,在传参和返回期间,函数不会直接传递实参或者将变量本身直接返回,而是传递实参或者返回变量的一份临时的拷贝,因此用值作为参数或者返回值类型,效率是非常低下的,尤其是当参数或者返回值类型非常大时,效率就更低。

#include <time.h>
struct A{ int a[10000]; };
A a;
// 值返回
A TestFunc1() { return a;}
// 引用返回
A& TestFunc2(){ return a;}
void TestReturnByRefOrValue()
{// 以值作为函数的返回值类型size_t begin1 = clock();for (size_t i = 0; i < 100000; ++i)TestFunc1();size_t end1 = clock();// 以引用作为函数的返回值类型size_t begin2 = clock();for (size_t i = 0; i < 100000; ++i)TestFunc2();size_t end2 = clock();// 计算两个函数运算完成之后的时间cout << "TestFunc1 time:" << end1 - begin1 << endl;cout << "TestFunc2 time:" << end2 - begin2 << endl;
}

通过上述的代码比较,不难发现传值和指针在作为传参以及返回值类型上面的效率相差很大。

6、6、引用和指针的区别

语法层面上引用就是别名,没有独立的空间,和引用的实体共同用一块空间。
但是,底层实现上实际是有空间的,因为引用是按照指针的方式去实现的。因为C++就是在C的基础上来进行进化的。

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

我们通过什么知道这两个是一样的呢?当然是通过计算机编译器的底层汇编来看啊。
在这里插入图片描述
引用和指针的不同点:
1、引用概念上的定义是变量的别名指针存储一个变量的地址
2、引用在定义的时候就必须初始化,指针没有要求。
3、引用在初始化时引用一个实体之后,就不能引用其他实体,而指针可以在任何时候指向任何一个同类型的实体。
4、没有NULL引用,但是有NULL指针。
5、sizeof的计算不同,引用的结果为引用类型的大小,但是指针始终是地址空间所占字节个数(32位平台下占4个字节)
6、引用自加1,即实体加1。指针自加则是向后偏移一个类型的大小。
7、有多级指针,但是没有多级引用
8、访问方式不同,指针需要显示解引用,引用编译器自己处理。
9、引用比指针使用起来相对来说更安全。

7、内联函数

7、1、概念

在函数最开始的时候用inline修饰的函数叫做内联函数,C++编译器会在调用内联函数的地方展开。但是由于编译器的不断提升,现在的编译器已经会判断函数是否应该展开,如果太长也不会展开的。那为什么需要**inline呢?**那是因为不需要调用函数,也就意味着没有函数调用建立栈的开销,内联函数提升程序运行的效率。
在这里插入图片描述
这是正常的函数调用。在这里插入图片描述
而这时内联函数的展开。

7、2、特性

1、 inline函数是一种空间换时间的做法,如果编译器将函数当作内联函数处理,在编译阶段,会用函数体替换函数调用
2、 inline对于编译器来说只是一个建议,不同的编译器实现的机制可能不同,一般来说:函数规模较小(函数不是很长,具体还是取决于编译器)、不是递归且频繁的调用的函数采用inline,否则编译器将会忽略inline的特性。
在这里插入图片描述
3、 inline不建议声明和定义分离 ,分离会导致链接错误。因为inline被展开,就没有函数地址了,链接就会找不到。

7、3、inline细节

首先看一下宏和函数的区别。
请添加图片描述
宏的优点和缺点在上述的图片中已经很清楚了,那么有没有什么办法能够在这些的优点上进行对缺点的改变?
C++中的可以代替宏的方案
1、常量定义 换成const enum
2、短小函数定义 换成内联函数

8、auto关键字(C++11)

随着程序的复杂化,类型的使用也将会是多样化。这就导致
1、类型难于拼写
2、含义不明导致出错

8、1、auto介绍

auto不再是一个存储类型指示符,而是作为一
个新的类型指示符来指示编译器,auto声明的变量必须由编译器在编译时期推导而得

int TestAuto()
{
return 10;
}
int main()
{
int a = 10;
auto b = a;
auto c = 'a';
auto d = TestAuto();
cout << typeid(b).name() << endl;
cout << typeid(c).name() << endl;
cout << typeid(d).name() << endl;
//auto e; 无法通过编译,使用auto定义变量时必须对其进行初始化
return 0;
}

==注意:==使用auto定义变量时必须对其进行初始化,在编译阶段编译器需要根据初始化表达式来推导auto
的实际类型。因此auto并非是一种“类型”的声明,而是一个类型声明时的“占位符”,编译器在编
译期会将auto替换为变量实际的类型

8、2、auto使用规则

1、 auto与指针和引用结合使用
用auto声明指针类型时,用auto和auto*没有任何区别,但用auto声明引用类型时则必须
加&

2、 同一行定义多个变量时,所有的变量必须是相同类型。
3、 auto不能作为函数的参数。同时,也不能声明数组。

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

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

相关文章

电脑/机顶盒/ps3/4/连接老电视(只有AV、S-Video接口)解决方案之HDMI转AV/S-Video转换器HAV

HDMI转AV/S-Video转换器功能 01、将HDMI高清信号经过视频处理转换成AV、S-VIDEO(PAL/NTSC)的视频信号输出 02、将HDMI数字音频&#xff0c;经过DAC数模芯片处理转成模拟立体声输出 03、采用先进的视频处理技术&#xff0c;对图像的亮度&#xff0c;对比度及色彩进行增强处理 04…

使用Docker本地部署Jupyter Notebook并结合内网穿透实现远程访问

文章目录 1. 选择与拉取镜像2. 创建容器3. 访问Jupyter工作台4. 远程访问Jupyter工作台4.1 内网穿透工具安装4.2 创建远程连接公网地址4.3 使用固定二级子域名地址远程访问 本文主要介绍如何在Ubuntu系统中使用Docker本地部署Jupyter Notebook&#xff0c;并结合cpolar内网穿透…

01-操作系统_名词_文件下载_反弹

操作系统_名词_文件下载_反弹 一、渗透测试1.1、POC、EXP、Payload与Shellcode1.2、后门1.3、木马1.4、反弹1.5、回显1.6、跳板1.7、黑白盒测试1.8、暴力破解1.9、社会工程学1.10、撞库1.11、ATT&CK 二、案例演示2.1、基础案例1&#xff1a;操作系统-用途&命令&权限…

Android学习之路(27) ProGuard,混淆,R8优化

前言 使用java编写的源代码编译后生成了对于的class文件&#xff0c;但是class文件是一个非常标准的文件&#xff0c;市面上很多软件都可以对class文件进行反编译&#xff0c;为了我们app的安全性&#xff0c;就需要使用到Android代码混淆这一功能。 针对 Java 的混淆&#x…

【Docker】Docker Registry(镜像仓库)

文章目录 一、什么是 Docker Registry二、镜像仓库分类三、镜像仓库工作机制四、常用的镜像仓库五、常用命令镜像仓库命令镜像命令(部分)容器命令(部分) 六、docker镜像仓库实战综合实战一&#xff1a;搭建一个 nginx 服务综合实战二&#xff1a;Docker hub上创建自己私有仓库综…

B站课程评分

Spring6 https://www.bilibili.com/video/BV1Ft4y1g7Fb/ 评价: 推荐一看 配套文档优秀, 老师口齿清晰, 条理不错. mybatis https://www.bilibili.com/video/BV1JP4y1Z73S/?spm_id_from333.337.search-card.all.click 评价: 推荐一看 配套文档优秀, 老师口齿清晰, 条理不错…

等变和不变 、向量神经元(vector neurons)是什么?

等变和不变 等变&#xff1a;如果输入是一个旋转后的椅子&#xff0c;那么输出也应该是一个旋转后的椅子 不变&#xff1a;如果输入是一个旋转后的椅子&#xff0c;那么输出应该是一个椅子&#xff0c;而不是一只狗。 向量神经元&#xff08;vector neurons&#xff09; 向量…

如何监控摄像头是否在线?有什么工具推荐

WGCLOUD监控系统 我们项目中&#xff0c;摄像头用的WGCLOUD监控系统来监控的&#xff0c;主要两种方式来监控 一种是监控摄像头的端口&#xff0c;使用WGCLOUD的端口监控模块 一种是PING摄像头的IP&#xff0c;使用WGCLOUD的ping监测模块 这两种方式比较简单&#xff0c;也…

1997-2022年中央对各省份一般公共预算转移支付数据

1997-2022年中央对各省份一般公共预算转移支付数据 1、时间&#xff1a;1997-2022年 2、范围&#xff1a;31省 3、指标&#xff1a;一般公共预算转移支付 4、来源&#xff1a;wind 财政部 5、指标解释&#xff1a;一般性转移支付又称体制性转移支付&#xff0c;是指上级政…

【2024.2.4练习】国王游戏

题目描述 题目思路 涉及排列组合求最优解问题&#xff0c;数据大考虑是否满足某种贪心策略。 假设不除以右手的数字&#xff0c;那么获得金币数量最多的显然为最后一个人。左手数字最大的应排在最后一位。在右手有数字的情况下&#xff0c;不妨也尝试从最后一个人开始排。 假…

Element UI+Spring Boot进行CRUD的实例

ElementUI安装与使用指南 前端代码&#xff1a;点击查看learnelementuispringboot项目源码 后端代码&#xff1a;点击查看 LearnElementUiAndSpringBoot 一、前端配置 安装axios axios官网axios中文文档安装指令&#xff1a;npm install axios 二、后端配置 springboot3m…

BLIP2——采用Q-Former融合视觉语义与LLM能力的方法

BLIP2——采用Q-Former融合视觉语义与LLM能力的方法 FesianXu 20240202 at Baidu Search Team 前言 大规模语言模型&#xff08;Large Language Model,LLM&#xff09;是当前的当红炸子鸡&#xff0c;展现出了强大的逻辑推理&#xff0c;语义理解能力&#xff0c;而视觉作为人…

YOLOv8进阶 | 如何用yolov8训练自己的数据集(以安全帽佩戴检测举例)

前言&#xff1a;Hello大家好&#xff0c;我是小哥谈。YOLOv8是一种目标检测算法&#xff0c;它是YOLO&#xff08;You Only Look Once&#xff09;系列算法的最新版本。本节课就带领大家如何基于YOLOv8来训练自己的目标检测模型&#xff0c;本次作者就以安全帽佩戴检测为案例进…

华为机考入门python3--(7)牛客7-取近似值

分类&#xff1a;数字 知识点&#xff1a; str转float float(str) 向上取整 math.ceil(float_num) 向下取整 math.floor(float_num) 题目来自【牛客】 import math def round_to_int(float_num): # 如果小数点后的数值大于等于0.5&#xff0c;则向上取整&#xf…

Fink CDC数据同步(一)环境部署

1 背景介绍 Apache Flink 是一个框架和分布式处理引擎&#xff0c;用于在无边界和有边界数据流上进行有状态的计算。Flink 能在所有常见集群环境中运行&#xff0c;并能以内存速度和任意规模进行计算。 Flink CDC 是 Apache Flink 的一组源连接器&#xff0c;基于数据库日志的…

【SpringBoot】RBAC权限控制

&#x1f4dd;个页人主&#xff1a;五敷有你 &#x1f525;系列专栏&#xff1a;SpringBoot⛺️稳重求进&#xff0c;晒太阳 权限系统与RBAC模型 权限 为了解决用户和资源的操作关系&#xff0c; 让指定的用户&#xff0c;只能操作指定的资源。 权限功能 菜单权限&a…

windows下安装go

下载golang Go 官网下载地址&#xff1a; https://golang.org/dl/ Go 官方镜像站&#xff08;推荐&#xff09;&#xff1a; https://golang.google.cn/dl/ 选择安装包 验证有没有安装成功 查看 go 环境 说明 &#xff1a; Go1.11 版本之后无需手动配置环境变量&#xff0c…

29 python快速上手

Python操作MySQL和实战 1. 事务1.1 MySQL客户端1.2 Python代码 2. 锁2.1 排它锁2.2 共享锁 3. 数据库连接池4. SQL工具类4.1 单例和方法4.2 上下文管理 5.其他总结 目标&#xff1a;掌握事务和锁以及Python操作MySQL的各种开发必备知识。 概要&#xff1a; 事务锁数据库连接池…

Weblogic反序列化漏洞分析之CVE-2021-2394

目录 简介 前置知识 Serializable示例 Externalizable示例 联系weblogic ExternalizableLite接口 ExternalizableHelperl类 JdbcRowSetImpl类 MethodAttributeAccessor类 AbstractExtractor类 FilterExtractor类 TopNAggregator$PartialResult类 SortedBag$Wrappe…

【测试运维】web自动化全知识点笔记第1篇:什么是Web自动化测试(已分享,附代码)

本系列文章md笔记&#xff08;已分享&#xff09;主要讨论Web自动化测试相关知识。了解什么是自动化&#xff0c;理解什么是自动化测试以及为什么要使用自动化测试。具体包含&#xff1a;WebDriver的基本操作&#xff0c;WebDriver的鼠标、键盘操作&#xff0c;下拉选择框、警告…