c++入门基本知识掌握

news/2025/3/18 20:08:01/

学习要求:1.关键词 (先大致看看哪些学过 不让你背下来 就让你看看)2.命名空间

                   3.输入输出(cin&cout)4. 缺省参数

                     5.函数重载    6. 引用 7. 内联函数

                     8. auto关键字 还有for-each(新用法) 9.nullptr的引入

warning: 以下的参考使用vs2022的编译器。

目录

一.关键字

   warning: 这里仅供观看 不过多叙述了,建议:你可以看看哪些没见过的留个印象。 如图1-1

二.命名空间

   1.命名空间中的引入呢:是祖师爷为了解决c语言中经常出现的命名问题,所以命名空间(域:具有限定作用的)出现了: namespace

2.命名空间的定义 

3.命名空间的使用方法 

三.输入输出 cin&cout

四.缺省参数 (oi说白了就是。。。)

1. 定义

2. 缺省参数几种类型

五.函数重载 (终于到这了 我挺不容易的点个赞呗)

1. 定义 

2. 注意点 

3. 扩展

六.引用 (太好了 救世主来了 )

1. 定义 

2. 使用

3. 具体实例

4.效率对比 

5. 区别与指针

七.内联函数 

1. 来源

2. 定义和使用 

  wanring:

八.auto和for-each的用法

九.nullptr指针的引入


一.关键字

   warning: 这里仅供观看 不过多叙述了,建议:你可以看看哪些没见过的留个印象。 如图1-1

            :C++ 总计 63 个关键字, C 语言 32 个关键字 

二.命名空间

   1.命名空间中的引入呢:是祖师爷为了解决c语言中经常出现的命名问题,所以命名空间(域:具有限定作用的)出现了: namespace

1. 创建了两文件   
test.c                                                                    test.cpp
c语言文件下出现重定义了,这是因为编译器在查找rand的时候会去库里面找 链接的过程中中之间拿来stdlib.h中的rand函数了 他当然看不懂啊! 所以这里的命名冲突是c语言很常见的。
比如一些企业中不同的项目之间分别完成一些模块啊 最后项目代码组合发现 oi!你的我的名字咋一样啊 那咋办 只能改名。 
所以这里引入了一个命名空间,限定了编译器查找变量时候先去你的域里面查找 就不会去外面在找了。

2.命名空间的定义 

1. 使用namespace 关键字 2. 后面加花括号就行 具体怎么定义看下面代码:
// 比如我现在开发一个项目使用到的函数啊 数据啊 都是要只是这一个项目里面的 那我就
//单独给这个项目开辟一个空间 用这个特定的项目也只用这块空间
// 假设这个项目是描述一个猴子山的 
namespace Project1 {// 猴子总数量int money_num = 999;// 在这个项目中可以定义函数 void fun(){;///}// 命名空间中还可以嵌套空间 而且这两个空间依然是独立 但是访问。。 namespace Project2 {// pig int pig_num = 888;void fun() {printf("这里是pig_project");}}}//补充  不同文件下都有同名的 namespace 最后编译器会整合到认为是同一个空间 
如 test.h test.c 下面你都有命名空间 namespace 但是内容不一样 但是依然会。。

3.命名空间的使用方法 

namespace N1{int Add(int x, int y) {return x + y;}int a1 = 999;int a2 = 888;
}// :: 作用域操作符 
using N1::a2;// 使用using+空间名称+:: + 变量名 拿出来变量 
int main()
{// 这里我要拿出来a1 a2 然后使用其中的函数并打印出结果int a1 = N1::a1;// 命名空间加上其中的变量名 int a2 = N1::a2;printf("%d",N1::Add(a1,a2));return 0;
}

值得注意的是还有一方法 就是直接展开这个全部的空间:

namespace N1 {int Add(int x, int y) {return x + y;}int a1 = 999;int a2 = 888;
}
using namespace N1;// using namespace+空间名 直接展开空间内的全部 int main()
{printf("%d", Add(a1, a2));return 0;
}

这个方法好处明显但是坏处更明显 就是空间之间没有那么独立了。 因为全部被展开了。 

但是话又说回来 : 我们为了方便学习 我们一般会之间展开标准库:为了使用其中的输入输出函数 ,哈哈哈 !

三.输入输出 cin&cout

要记住一个事情就是c++啊 他兼容c 所以c里面的你c++都能用 反之就不行了哈哈哈!
#include<iostream> // 记住这是你跨入c++大门的第一步 以后再也不用c中的stdio.h了 哈哈哈 
using namespace std; // 展开这个标准库空间 要用到 里面的输入输出 int main()
{cout << "hello world" << endl;cout << "hello world" << "";return 0;
}

输出结果:

很棒的你应该猜到了二者输出的区别 : endl(这是l    L的小写)结束他换行了 “”结尾 没有换行 
这就是cout 输出流   简单来说以后用他输出 当然他也有很多方便的地方 就是: 以后咱不用使用占位符了: 看看下面的代码吧
int main()
{/*cout << "hello world" << endl;cout << "hello world" << "";*/float pi;int a;int b;cin >> pi;cin >> a >> b;cout << pi << " " << a << " " << b << " ";return 0;
}

oi! 看看下面为什么报错啦 你这么棒一定知道的。
总结一下: cin<< 简单方向不能错(cout>> 其中 可以之间放字符串 也可以直接放变量 不用确定他类型这是因为什么呢 后面学了重载函数你在看看这 这个自动识别 其实很简单实现)

四.缺省参数 (oi说白了就是。。。)

( 就是白说了 开个玩笑哈 哈哈哈 )
warning : 这家伙c语言可没有哈 又给你装到了

1. 定义

具体来说 就是给函数参数提供了一个默认值,然后具有默认值的家伙(形参)叫做缺省参数。
来看看下面的结果 根据你的感觉-----
void fun1(int x = 100)
{cout << x << endl;}int main()
{fun1();fun1(521);return 0;
}
你的结果:  (错了 惨不忍睹 笑死)  (对了 算你小子运好)
实际结果:
结论 :我们可以不传参如果有默认值 (或者说有缺省参数) 但是如果传递传了实参那你老老实实的------

2. 缺省参数几种类型

//全缺省参数
void Func(int a = 10, int b = 20, int c = 30)
{cout << "a = " << a << endl;cout << "b = " << b << endl;cout << "c = " << c << endl;
}//半缺省参数 // oi 注意啊 别乱搞这里的半缺省就是有一个不是缺省参数的家伙就叫半缺省 
void Func(int a, int b = 10, int c = 20)
{cout << "a = " << a << endl;cout << "b = " << b << endl;cout << "c = " << c << endl;
}

细节决定成败 来我们copy一下别人的:

1. 半缺省参数必须 从右往左依次 来给出,不能间隔着给
2. 缺省参数不能在函数声明和定义中同时出现// 这里解释一下 说白了 就是 你定义和声明如果都要不一样的默认值 编译器就懵逼了啊 如 test.c下你定义了  test.h下你声明了

五.函数重载 (终于到这了 我挺不容易的点个赞呗)

我真的想夸夸祖师爷哈 这家伙打小就聪明 这想法很赞  这可是c语言没有的哈 
: 还记得前面出现 如果说别人用过了这个函数名你不能用的情况吗 来 废话不多说 直接上 

1. 定义 

// 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;
}

oi: 震惊 只学过c语言的同学包的 挖去 你这这这 怎么都一样的函数名调用哦 会不会出问题哦 编译器不报错我吃。

    包的: 这里啊 下面构成函数重载 :函数名相同的情况下: 1.形参个数不同 2.形参类型不同3.形参类型顺序不同 

 有个小可爱问我 (其实我自己就是这个小可爱):你你你 形参名字不一样怎么办 形参名字有什么鬼用 重要的是类型 比如   void fun(int x ,int y)   void fun (int y, int x)   作为一个标准的好孩子 都知道这两家伙是一个人 不能构成函数重载 

:------- 相同的名字 可以不同的人 

2. 注意点 

void fun(int x, int y = 1, int z) {;
}void fun(int x, int y, int z) {;
}

 有人问 (我问)你你你 我可是缺省参数, 那咋了 你缺省参数那咋了 跟我函数有什么关系 我关注的几个点里面不包括你的缺省参数所以别管他们两不构成重载函数  

3. 扩展

大胆问我 :为什么啊 为什么c语言不支持重载呢? 这里我先直接跟你解答 我们在看看底层 
c语言传递参数的时候: 我们举个栗子
对于图片中的代码呢 c语言中 调用fun函数的时候是根据fun去找函数的定义 
然后使用对应的参数   
c++中呢 是这样的 调用fun函数的时候会有fun +int +double +char 去查找这个函数  所以函数重载来自这里 
如何具体看看呢 :我们可以去看看底层的汇编代码 我们都知道程序运行过程包括: 预处理  编译 汇编 链接
所以我们去看看汇编代码中的调用函数是什么样的你就理解了
操作如下 :  1. 先进入调式状态  2.  右键鼠标点击到反汇编
看到这一串了吗 其实这是被修饰之后的调用函数 对应的签名我们可以查表 大概 得到也就是 fun(int ,double,char) 
而c语言是 fun()

六.引用 (太好了 救世主来了 )

1. 定义 

引用 : 就好像取别名一样 比如我叫李二蛋 但是别人随便给我取了一个别名 :狗子 
所以叫我大名是我李二蛋这个人 叫我狗子还是我这个人啊 
语法上 : 引用变量 跟被引用的变量二者公用一块内存  当然对应的地址肯定一样啦 如下图 
初始化一下:
int a = 10;
int&ra = a;

2. 使用

1. 引用在 定义时必须初始化
2. 一个变量可以有多个引用
3. 引用一旦引用一个实体,再不能引用其他实体

4. 注意不能引用常变量(如被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; // 该语句编译时会出错,类型不同const int& rd = d;
}

牛刀小试: 思考下面为什么报错 

答案 (因为 NULL空 被认为是常量0啊 当然不能被引用,或者说 逻辑上 空是不能被改变的不能被引用)

3. 具体实例

//做参数
void Swap(int& left, int& right)
{int temp = left;left = right;right = temp;
}
//做返回值 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;
}

做返回值这里呢 如果你返回一个引用了 函数中的参数呢 出了作用域被销毁了 这里的add函数输出结果呢对应应该是随机值咯 这里涉及到函数栈帧的知识可以参考我前面的作品哦。

4.效率对比 

    以值作为参数或者返回值类型,在传参和返回期间,函数不会直接传递实参或者将变量本身直
接返回,而是传递实参或者返回变量的一份临时的拷贝,因此用值作为参数或者返回值类型,效
率是非常低下的,尤其是当参数或者返回值类型非常大时,效率就更低。
嘿 ! 注意哦 : 语法概念上 引用就是一个别名,没有独立空间,和其引用实体共用同一块空间
但是 !我说但是啊 :  底层实现上 实际是有空间的,因为 引用是按照指针方式来实现 的。
  
汇编代码 : 底层二者其实没什么区别 但是 使用起来不同而已

5. 区别与指针

引用和指针的不同点 :
1. 引用概念上定义一个变量的别名,指针存储一个变量地址。
2. 引用在定义时必须初始化,指针没有要求
3. 引用在初始化时引用一个实体后,就不能再引用其他实体,而指针可以在任何时候指向任何
一个同类型实体
4. 没有NULL引用,但有NULL指针
5. 在sizeof中含义不同引用结果为引用类型的大小,但指针始终是地址空间所占字节个数(32
位平台下占4个字节)
6. 引用自加即引用的实体增加1,指针自加即指针向后偏移一个类型的大小

七.内联函数 

1. 来源

在这之前我们先复习一下宏 : 在预处理阶段会把宏展开:

// 宏的使用 
// 宏变量 
#define N 100
// 宏函数 写一个add
#define Add (x,y) ((x)+(y))

   这里忘记的孩子,感觉去搜一下宏函数 宏变量的使用方法吧 

宏的优点: 1.可读性 2. 复用性 3. 提高代码运行效率 (如函数调用时减少开销代价 )

缺点也挺明显的: 1. 不可以调试错误 2. 没有类型错误检查

   所以c++ 出来了一个叫 内联函数的家伙 :

2. 定义和使用 

    内联函数是对于: 1. 非递归 2. 规模较小的 3. 调用频繁的函数 编译器会直接在当前运行代码的位置直接展开该函数减小函数调用的开销 

inline int add(int x,int y)
{int b = x+y;
return b;
}

   在这类函数的前面加上inline

 这是一种用空间换时间的思路 但是如果过于大的调用 可能会导致代码膨胀 使得文件很大 所以编译器其实对于内联函数用不用是有自己的思路的: 一般来说 3-4行的代码吧 他可能会内联    

  wanring:

     这里最容易犯错误的地方就是内

inline int add (int x,int y);int  add(int x,int y){return x+y;}

联函数的声明和定义不要分离: 这里在调用的时候 会出现链接错误 因为声明inline直接被展开了后面函数调用的时候找不到函数地址了 就调用不了函数了 ;所以请注意内联函数:声明和定义一定要在同一地方不要分离了;

八.auto和for-each的用法

 auto 这家伙 

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

int main()
{int x = 10;auto a = &x;// 这个auto的声明 auto 是int*auto* b = &x;// 这里auto 识别出是int型 auto& c = x;// 类似 auto这里是 int型cout << typeid(a).name() << endl;cout << typeid(b).name() << endl;cout << typeid(c).name() << endl;*a = 20;*b = 30;c = 40;return 0;
}
void TestAuto()
{auto a = 1, b = 2; auto c = 3, d = 4.0;  // 该行代码会编译失败,因为c和d的初始化表达式类型不同
}
// 此处代码编译失败,auto不能作为形参类型,因为编译器无法对a的实际类型进行推导
void TestAuto(auto a)
{}
void TestAuto()
{int a[] = {1,2,3};auto b[] = {4,5,6};
}
比
2. auto 不能直接用来声明数组

每个 auto 声明都是独立进行类型推断的 

for -each 输出每一个成员内容 

对于一个 有范围的集合 而言,由程序员来说明循环的范围是多余的,有时候还会容易犯错误。因
C++11 中引入了基于范围的 for 循环。 for 循环后的括号由冒号 分为两部分:第一部分是范
围内用于迭代的变量,第二部分则表示被迭代的范围

void TestFor()
{
int array[] = { 1, 2, 3, 4, 5 };
for(auto& e : array)e *= 2;
for(auto e : array)cout << e << " ";
return 0;
}

这上面 如果你要改变其中的内容 你可以用引用 注意这里呢auto自动的变量类型是数组的元素类型

   值得注意的是java中也有类似的语法。

九.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;
}

 这个代码中你以为F(NULL) 会调用 f(int*) 然而是 f(int ) 那是因为 在底层中 NULL其实是一个宏变量 值为 0  有的编译器下是 (void*) 

 但是吧 为了兼容以前的版本正确含义应该是 (void*)类型的 的空指针 所以 创建了一个新的关键字 nullptr 类型为void*


http://www.ppmy.cn/news/1580149.html

相关文章

搭建opensbi+kernel+rootfs及基本设备驱动开发流程

目录 一.编译qemu 运行opensbikernelrootfs 1.编译qemu-9.1.1 2.安装riscv64编译器 3. 编译opensbi 4.编译kernel 5.编译rootfs 设备驱动开发流程 1.安装 RISC-V 交叉编译工具链 2.驱动开发准备 3.编写简易中断控制器驱动&#xff08;PLIC&#xff09;​ 4.配置内核…

Python基于Django和协同过滤算法实现电影推荐系统功能丰富版

说明&#xff1a;这是一个系统实战项目&#xff0c;如需项目代码可以直接到文章最后关注获取。 项目背景 随着互联网的普及和数字娱乐内容的爆发式增长&#xff0c;用户在海量的电影资源中找到自己感兴趣的影片变得愈发困难。为了提升用户体验并增加用户粘性&#xff0c;我们…

C/C++蓝桥杯算法真题打卡(Day6)

一、P8615 [蓝桥杯 2014 国 C] 拼接平方数 - 洛谷 方法一&#xff1a;算法代码&#xff08;字符串分割法&#xff09; #include<bits/stdc.h> // 包含标准库中的所有头文件&#xff0c;方便编程 using namespace std; // 使用标准命名空间&#xff0c;避免每次调用…

Microsoft Outlook 2024 LTSC for Mac v16.95 电子邮件和日历 支持M、Intel芯片

应用介绍 Microsoft Outlook 2024 LTSC for Mac 是微软为Mac用户推出的一款电子邮件管理和日历应用&#xff0c;属于长期服务通道&#xff08;LTSC&#xff09;版本&#xff0c;适合需要稳定性和长期支持的企业用户。它提供了强大的邮件管理功能、日历功能以及团队协作工具&am…

深度学习 Deep Learning 第1章 深度学习简介

第1章 深度学习简介 概述 本章介绍人工智能&#xff08;AI&#xff09;和深度学习领域&#xff0c;讨论其历史发展、关键概念和应用。解释深度学习如何从早期的AI和机器学习方法演变而来&#xff0c;以及如何有效解决之前方法无法应对的挑战。 关键概念 1. 人工智能的演变 …

【最佳实践】Go 状态模式

设计思路 状态模式的核心在于将对象的行为封装在特定的状态类中&#xff0c;使得对象在不同的状态下表现出不同的行为。每个状态实现同一个接口&#xff0c;允许对象在运行时通过改变其内部状态对象来改变其行为。状态模式使得状态转换更加明确&#xff0c;并且易于扩展新的状…

coding ability 展开第四幕(滑动指针——巩固篇)超详细!!!!

文章目录 前言水果成篮思路 找到字符串中所有字母异位词思路 串联所有单词的子串思路 最小覆盖子串思路 总结 前言 本专栏上一篇博客&#xff0c;带着大家从认识滑动窗口到慢慢熟悉 相信大家对滑动窗口已经有了大概的认识 其实主要就是抓住——一段连续的区间 今天来学习一些滑…