「C++」入门

🎇个人主页:Ice_Sugar_7
🎇所属专栏:C++启航
🎇欢迎点赞收藏加关注哦!

文章目录

  • 🍉前言
  • 🍉命名空间
    • 🍌访问命名空间中的元素
    • 🍌同名命名空间
    • 🍌展开
      • 🥝指定展开
  • 🍉io流
    • 🍌基本的输入输出
  • 🍉缺省参数
    • 🍌使用规则
  • 🍉函数重载
    • 🍌补充
  • 🍉引用
    • 🍌注意事项
    • 🍌常引用
    • 🍌相关应用
      • 🥝传参
      • 🥝作为返回值
    • 🍌引用的底层实现
    • 🍌引用与指针的区别
  • 🍉内联函数
    • 🍌基本概念
    • 🍌注意事项&建议
  • 🍉关键字:auto
  • 🍉范围for循环
  • 🍉指针空值nullptr

🍉前言

cpp在绝大部分情况下都兼容C语言,相当于C语言的拓展,所以在正式进入cpp的世界之前,我们得先了解相较于C语言,cpp有哪些不同之处,然后才能入门。

🍉命名空间

在写代码的过程中,我们自己写的函数可能与库函数冲突(函数名相同),而在一个项目中,我定义的某个类型或者函数有可能和你的定义一样,我们单独运行自己的代码没问题,但是一旦合并到一个项目中运行就会产生冲突。
这时除了改变我们两人其中一个的代码的名字,我们可以使用命名空间,它的形式如下:

namespace space {
	int a = 0;
}

类似结构体,但是大括号后面没有分号,里面可以存放变量、函数、某种类型等

命名空间相当于一堵墙,将其中的元素与全局隔离开了,在找变量的时候,会去找全局中的变量,哪怕找不到,也不会去找命名空间中的。

🍌访问命名空间中的元素

访问的话很简单,只需按照命名空间名 + :: + 你想访问的元素的格式就ok,例子如下:

namespace space {
	int c = 10;
}
	int a = 10;
	printf("%d\n", space::c);

🍌同名命名空间

多个文件中含有同名的命名空间,它们不会产生冲突。

比如你在头文件里面定义了一个命名空间,源文件里面也有一个同样的命名空间,这个源文件在包含头文件的时候,编译器会自动识别将它们进行合并,因此不会发生冲突。

🍌展开

展开就相当于你把这堵围墙给拆了

展开后搜索顺序
我现在同时展开两个命名空间,又定义了一个变量,那会如何搜索呢?

	using namespace a
	{
		//...
	};
	using namespace b
	{
		//...
	};

规则是这样的:先搜索全局,全局找到了就不会搜索这两个命名空间;如果找不到再来它们里面找,从上往下找,即先找a,a找不到再找b,a找到的话那自然不用去b里面找咯。(都找不到的话那就报错了)

拓展:
头文件展开:在预处理阶段把头文件的内容拷贝过来
命名空间展开:默认访问命名空间中的变量而非全局中的变量

只要你展开了,那默认就会去命名空间中搜索,不用每次都要去指定。(要指定也可以,只不过一般不那么做)

那接下来我们来看下它是啥意思

	using namespace std;

std是cpp官方库定义的命名空间,cpp库里面的东西都在它里面,你把它展开之后就可以使用cpp的东西了

注意:以后在工程项目中,不要随便展开std,因为很有可能会与里面的函数发生冲突(不然你想下为啥要把它们封装在std里面),而现在日常的练习之中,由于代码量比较小,发生冲突的概率很小,所以一般就直接展开了。

🥝指定展开

不展开的话每一次都要指定很麻烦,全部展开的话又会有冲突的风险,那怎么办呢?这时候就要用到指定展开
要用啥就展开啥,只展开一部分才是最稳妥的方式

using space::add;	//只展开space中的函数add,此时可在任意位置使用add

🍉io流

我们在cpp中通常会包含这样一个头文件:

#include<iostream>

里面包含cin、cout、<<等输入输出函数,相当于C语言的stdio.h,然后注意cpp中包含io流不用写“.h”

在C语言中 << 是一个位运算符,在cpp中它有了新的含义一一流插入运算符;相应地,>>叫做流提取运算符
(说到流入和提取,以及看到 in 和 out,不禁回想起之前学习文件操作时接触到的“输入流”和“输出流”,输入流就是把流里面的数据给到文件,而输出流则是把数据从文件中提取出来,放到流里面。)

🍌基本的输入输出

using namespace std;

int main(){
	int a = 10;
	cout << a << endl;
	int b;
	cin >> b;
	cout << b << endl;
	int c, d;
	cin >> c >> d;  //输入两个数
	cout << c << ' ' << d << endl;  //输出c,d并用空格分隔
	return 0;
}

输出结果:
在这里插入图片描述
cpp中的cout会自动识别类型,不用和printf一样还要去区分%d,%lf 什么的,比如上面把c改为浮点型,照样可以正常输出。

关于控制浮点数位数以及左、右对齐:这两个点用cin和cout不好实现,但是我们可以用printf,毕竟cpp兼容C语言,两个混用也是ok的,哪个方便用哪个就是了。


🍉缺省参数

以前学C语言的时候,如果函数如果有形参,那我们传参时就要传个参数过去。而C++中有了缺省参数这个概念,我们可以选择不传参,此时缺省参数会作为参数进行传参。其实说白了它就相当于一个备胎,实参部分有参数时就轮不到它,没有的时候才能上场。

int mul(int a = 10, int b = 20) {
	return a * b;
}

int main() {
	int a, b;
	cin >> a >> b;
	cout << mul(a, b)<< endl;
	cout << mul() << endl;  //使用缺省参数
}

在这里插入图片描述

🍌使用规则

使用缺省参数时需注意:
①只能自右向左缺省,若有多个缺省参数,则必须连续缺省,比如下面两个函数声明就犯了这种错误。

int func1(int a = 10, int b, int c);   //不是从右向左缺省
int func2(int a = 10, int b,int c = 20);   //没有连续缺省

②函数不能在声明和定义同时出现缺省参数
这样规定的理由其实很好理解,要是你声明函数和定义函数时设置的缺省参数不一样的话,那就不知道要选谁作为缺省参数了。(一般函数声明和定义不在同一个文件)
③缺省参数值只能为常量或者全局变量


🍉函数重载

cpp支持函数重载,在函数名相同的情况下,只要参数不一样,那么这两个函数就可以共存。

参数不同包括:①参数类型不同;②参数个数不同

比如

int func(int x, char y);
int func(char x, int y);

C语言在链接时是通过函数名去寻找函数地址,所以不允许出现同名函数;而cpp中采用函数名修饰规则,链接时根据修饰后的函数名去寻找函数的地址
在Linux环境下,通过指令 objdump -S 可执行程序可以查看函数名修饰后的情况。
比如,对于下面这个函数:

void func(int a,double b) {
	//...
}

如下图,可以看到它的函数修饰名为_Z4funcid
其中_Z为函数修饰名前缀;4表示函数名所占的字符数i表示整型参数;d表示双精度浮点型的参数。同时你会发现函数修饰名中没有包含返回值,这也说明两个函数仅有返回值不同是无法构成重载的
在这里插入图片描述

🍌补充

将一个源文件转化为可执行程序(.exe)需要经过预处理、编译、汇编和链接四个步骤

预处理阶段会进行头文件展开、宏替换、条件编译(去除条件语句中不用执行的语句)、去除注释等操作
编译阶段会检查语法,生成汇编代码,编译错误就是因为语法出错
汇编阶段会将汇编代码转换为二进制的机器代码
链接阶段会将各个文件合并起来,链接一些还没有确定的函数地址

将代码转到反汇编可以看到汇编代码,如下:
在这里插入图片描述其中的push、mov、sub都是我们可以看懂的,但是机器只认识二进制代码,所以汇编阶段要将它们转为二进制。


🍉引用

引用是给一个已经存在的变量再起一个“别名”,它和被引用的变量共用同一块内存空间
在这里插入图片描述
(如上图,b就是a的引用)

🍌注意事项

①引用必须初始化,即不能直接 int& b;
②一个变量可以同时有多个引用。毕竟是别名,多起几个也没事儿。

	int a = 1;
	int& b = a;
	int& c = b;
	int& d = a;

③引用无法改变指向。如下图,比如b是a的指向,那么就不能再让b成为c的引用。也正是这个特性,使得引用无法完全替代指针
在这里插入图片描述

🍌常引用

我们都知道,常量不可以被修改,但是引用可以对原数据进行修改,所以直接对常量进行引用就相当于放大了权限(从不可修改变为可以修改),编译器会报错。想引用常量的话,只需在引用前面加上const就ok了。

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

🍌相关应用

🥝传参

在实现单链表的尾插时,我们说当链表为空,想插入节点要传链表的二级指针,这样才能改变节点。但是这样确实很麻烦,也不好理解。而对于引用,由于它作为函数形参时,和实参共用同一块空间,所以改变它会影响实参,比传二级指针简洁多了。下面以这个函数为例进行对比
指针

void SLPushBack(SLNode** pphead,SLTypeDate x) {
	assert(pphead);  //进行断言,防止传过来的指针为空
	SLNode* node = SLBuyNode(x);
	if (*pphead == NULL) {  //phead为空说明此时链表为空,那就直接插入
		*pphead = node;  //让node是第一个节点的地址
		return;
	}
	//若不为空,则先找到链表的最后一个节点,再插入
	SLNode* pcur = *pphead;  //老样子,用临时变量pcur去走循环
	while (pcur->next) {
		pcur = pcur->next;
	}
	//此时pcur指向最后一个节点
	pcur->next = node;
}

引用

void SLPushBack(SLNode*& phead, SLTypeDate x) {
	assert(phead);  
	SLNode* node = SLBuyNode(x);
	if (phead == NULL) {  
		phead = node;  
		return;
	}
	SLNode* pcur = phead;  
	while (pcur->next) {
		pcur = pcur->next;
	}
	pcur->next = node;
}

🥝作为返回值

传值返回首先会对返回值进行拷贝,然后返回这份拷贝;对于传引用返回,也就是返回n的别名(你不用去理会这个别名叫什么,编译器会自行处理的,或者直接理解为返回n)。那此时到底会返回什么呢?这取决于栈帧结束后编译器会不会将栈帧内的值置为随机值并清理掉。我们来做个测试看看vs2022的编译器是否会进行清理。

int& test1(int i) {
	int data = i;
	return data;
}

int main() {
	int& ret = test1(10);
	cout << ret << endl;
	return 0;
}

在这里插入图片描述
由此可见,vs2022在函数栈帧结束后不会将栈帧中创建的变量清理掉

🍌引用的底层实现

在语法概念上,指针有开辟一块空间,而引用没有独立的空间。
不过对于这段代码,我们进行调试并转到反汇编观察一下。

	int x = 1;
	int* px = &x;
	int& y = x;

在这里插入图片描述
可以看到,引用和指针的汇编代码一模一样,说明引用在底层实现实际上是有开辟空间的,因为引用是按照指针的方式来实现的,即引用的底层是通过指针实现的
尽管如此,你也不要与上面的语法概念产生混淆,因为语法概念是上层的,而汇编是底层的。我们要按照语法概念来理解,默认引用就只是个别名

🍌引用与指针的区别

在现阶段大部分场景下,只要不涉及改变指向,就基本可以用引用代替指针。下面总结一下二者的区别(有一些上面已经讲过了,就不再赘述):

有NULL指针,但没有NULL引用,
引用自加即引用的实体增加1,指针自加即指针向后偏移一个类型的大小
有多级指针,但是没有多级引用
访问实体方式不同,指针需要显式解引用,引用编译器自己处理
引用比指针使用起来相对更安全(比如说有野指针,但是没有野引用)
在sizeof中含义不同:引用结果为引用类型的大小,但指针始终是地址空间所占字节个数(32位平台下占4个字节)


🍉内联函数

🍌基本概念

用inline修饰的函数叫做内联函数,在编译阶段,C++编译器会在调用内联函数的地方展开,用函数体替换函数调用,没有函数调用建立栈帧的开销,可以提升程序运行的效率。
注意:在release模式下才会展开,debug模式下仍然会调用函数(因为debug模式下,编译器默认不会对代码进行优化)。

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

int main() {
	
	cout << Add(1, 2) << endl;
	return 0;
}

在debug模式下观察汇编代码:
在这里插入图片描述
在release模式下,没有跳转到Add函数的指令:
在这里插入图片描述

🍌注意事项&建议

假设现在要实现一个栈,那就需要有Stack.h、Stack.cpp和test.cpp三个文件。
如果声明时在函数前面加上inline使其变为内联函数(假设在编译时这个函数会展开),那么会产生什么影响呢?

对于test.cpp文件,里面只有包含的头文件(函数声明)和函数的调用,在链接的时候需要去找函数的地址(链接时每个cpp文件生成的.o文件中都有一个符号表),但是内联函数的地址是不会进入符号表的,所以也就找不到它的地址了,就会产生链接错误了。
对于Stack.cpp文件,因为它本身就有函数的实现,编译时函数体直接展开,因此不需要得到函数的地址

所以我们可以得到这样的结论:一个内联函数如果声明和定义不在同一个文件的话,那么你就不能在其他文件(除Func.h 和 Func.cpp 之外的文件)中调用它
下面是一个链接错误的例子:

// F.h
#include <iostream>
using namespace std;
inline void f(int i);

// F.cpp
#include "F.h"
void f(int i)
{
 cout << i << endl;
}

// main.cpp
#include "F.h"
int main()
{
 f(10);
 return 0;
}
// 链接错误:main.obj : error LNK2019: 无法解析的外部符号 "void __cdecl 
f(int)" (?f@@YAXH@Z),该符号在函数 _main 中被引用

内联确实可以提高运行效率,但是不可乱用,比较大的函数采用内联直接展开的话会增加占用空间,使生成的可执行程序变大。为了防止程序员滥用,内联函数最终是否展开取决于编译器的处理,也就是说内联相当于是向编译器发出请求,编译器可以执行,也可以忽略。一般较大的函数即使加了inline,编译器也会忽略,不会直接展开。
所以,建议代码量较小的频繁调用的函数在前面加inline。


🍉关键字:auto

随着程序越来越复杂,程序中用到的类型也越来越复杂,体现在:

①类型难于拼写
②含义不明确导致容易出错

为了解决这些问题,C++11中,auto可以识别右值的类型并自动转换为相应的类型
在愉悦地上手auto之前,有如下的注意事项:

auto定义变量时必须初始化
用auto声明指针类型时,用auto和auto*没有任何区别,但是用auto声明引用类型时必须加&

int main()
{
    int x = 10;
    auto a = &x;
    auto* b = &x;
    auto& c = x;
    cout << typeid(a).name() << endl;  //获取变量a的类型,了解即可
    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不能做函数参数,也不能做返回值


🍉范围for循环

C++11中引入了基于范围的for循环,for循环后的括号由冒号:分为两部分:第一部分是范围内用于迭代的变量,第二部分则表示迭代的范围
光看文字肯定看不太懂,看下程序就明白了

void TestFor()
{
	int array[] = { 1, 2, 3, 4, 5 };
	for(auto& e : array)  //一般用auto,这样数组类型改变的时候你不用去修改
    	e *= 2;
	for(auto e : array)
    	cout << e << " ";
	return 0;
}

对于第一个范围for循环,就是依次取数组中的元素,然后赋值给e,再让e乘2,因为这里使用了引用,所以改变e就会改变数组中的元素。数组第一个元素乘2之后会自动往后走(相当于i++),让第二个元素赋值给e之后乘2…直到最后一个元素,然后自动判断结束。
如果不使用引用,写为for(auto e:array)的话,在循环中让e*2不会改变数组中的数据,因为只是把数组的值赋给e,改变e当然没法改变数组元素的值咯。

范围for相比与以前for循环,最大的进步就是不用自己去判断循环的终止条件了,这样既节省了时间,也可以避免写错终止条件而出错。

照例还是有一些注意事项:

①范围for中的数组名指的是整个数组(类比sizeof(数组名)),所以数组作为函数参数时,不能在函数中使用范围for,因为此时数组名表示的是首元素地址
②与普通循环类似,可以用continue来结束本次循环,也可以用break来跳出整个循环
③范围for循环迭代的范围必须是确定的(对于数组而言,就是数组中第一个元素和最后一个元素的范围)
④迭代的对象要实现++和==的操作


🍉指针空值nullptr

在C++中,NULL被编译器识别为0而非void*
可以用以下程序证明:

void TestNULL(int* p) {
	cout << "int*" << endl;
}

void TestNULL(int p) {
	cout << "int" << endl;
}

int main() {
	TestNULL(NULL);  //根据输出结果判断NULL的类型
	return 0;
}

在这里插入图片描述
如果NULL是0的话,那么用它来给指针置空的话,很可能会出问题。
为了修补这个漏洞,C++11中引进nullptr专门给指针置空。因此以后对于指针类型的变量,如果我们要初始化为空,就用nullptr

注意事项:

①因为nullptr是C++11新的关键字,所以在使用nullptr表示指针空值时,不需要包含头文件,
②在C++11中,nullptrvoid*所占的字节数相同
③为了提高代码的健壮性,在后续表示指针空值时建议最好使用nullptr

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

SAP smartforms二维码输出

此方法需要SAP_BASIS版本在731以上 TCODE-SE73 选择’系统条形码’点击 ‘更改’ 按步骤创建一个系统条形码 Module Size 调节二维码的尺寸 进入smartforms 创建样式 填入条形码名称 创建一张表单测试二维码&#xff0c;填入创建好的样式 测试结果&#xff1a;

显示器校准软件BetterDisplay Pro mac中文版介绍

BetterDisplay Pro mac是一款显示器校准软件&#xff0c;可以帮助用户调整显示器的颜色和亮度&#xff0c;以获得更加真实、清晰和舒适的视觉体验。 BetterDisplay Pro mac软件特点 - 显示器校准&#xff1a;可以根据不同的需求和环境条件调整显示器的颜色、亮度和对比度等参数…

Ansible的重用(include和import)

环境 管理节点&#xff1a;Ubuntu 22.04控制节点&#xff1a;CentOS 8Ansible&#xff1a;2.15.6 重用 Ansible提供四种可重用的工件&#xff1a; variable文件&#xff1a;只包含变量的文件task文件&#xff1a;只包含task的文件playbook&#xff1a;可包含play、变量、ta…

***Linux常用命令及解释

1、查看Linux的版本信息 1.1、uname -a 1.2、cat /etc/issue 1.3、cat /proc/version 1.4、hostnamectl 通过使用hostnamectl命令&#xff0c;可以查询和更改系统主机名&#xff0c;并且还可以查看Linux的发行版和内核版本。 2、删除文件 3、修改目录权限 4、解压文件 5、…

vue3(二)-基础入门

一、列表渲染 of 和 in 都是一样的效果 html代码&#xff1a; <div id"app"><ul><li v-for"item of datalist">{{ item }}</li></ul><ul><li v-for"item in dataobj">{{ item }}</li></u…

【教学类-06-10】20231125(55格版)X-Y之间“乘法×题”(以1-9乘法口诀表为例)(随机抽取和正序抽取)

图片展示 &#xff08;随机打乱排序&#xff09; 正序&#xff08;每张都一样&#xff09; 背景需求&#xff1a; 2023年11月24日&#xff0c;准备了一些题目&#xff0c;分别给大4班孩子介绍“5以内加法、5以内减法、5以内加减混合”““10以内加法、10以内减法、10以内加减…

数据结构 / 结构体字节计算

1. 结构体的存储 结构体各个成员的地址是连续的结构体变量的地址是第一个成员的地址 2. 64位操作系统8字节对齐 结构体的总字节大小是各个成员字节的总和&#xff0c;字节的总和需要是最宽成员的倍数结构体的首地址是最宽成员的倍数结构体各个成员的偏移量是该成员字节的倍数…

burpsuite的大名早有耳闻,近日得见尊荣,倍感荣幸

问题&#xff1a; burpsuite中文乱码何解&#xff1f; burpsuite 与君初相识&#xff0c;犹如故人归。 burpsuite早有耳闻&#xff0c;近日得见真容&#xff0c;果然非同凡响。 Burp Suite is a comprehensive suite of tools for web application security testing. burp …

C编译过程

寻觅GCC 如果你已经安装了Clion&#xff0c;那么gcc就在根目录下。 如果没有&#xff0c;那么需要去minGW的官网下载安装。添加到环境变量中。 编写C代码 #include <stdio.h>#define ARRAY_SIZE(a) sizeof(a)/sizeof(a[0]) static int a 123;int main() {int i 0;c…

2、Burp使用

文章目录 一、为Firefox浏览器安装数字证书二、利用Intruder模块进行暴力破解 一、为Firefox浏览器安装数字证书 &#xff08;1&#xff09;利用Firefox浏览器访问http://burp或127.0.0.1:<监听端口>&#xff0c;点击页面右上侧的“CA Certificate”处下载CA证书&#xf…

【UCAS自然语言处理作业二】训练FFN, RNN, Attention机制的语言模型,并计算测试集上的PPL

文章目录 前言前馈神经网络数据组织Dataset网络结构训练超参设置 RNN数据组织&Dataset网络结构训练超参设置 注意力网络数据组织&Dataset网络结构Attention部分完整模型 训练部分超参设置 结果与分析训练集Loss测试集PPL 前言 本次实验主要针对前馈神经网络&#xff0…

不同品牌的手机可以则哪一个你投屏到电视?

如果你使用AirDroid Cast的TV版&#xff0c;苹果手机可以通过airPlay或无线投屏方式&#xff0c;将屏幕同步到电视屏幕&#xff1b;多个品牌的安卓手机可以通过无线投屏投射到电视。而且无线投屏不限制距离&#xff0c;即使是远程投屏也可以实现。 打开AirDroid Cast的TV版&…

鸿蒙(HarmonyOS)应用开发——装饰器

简介 ArkTS是HarmonyOS优选的主力应用开发语言。它在TypeScript&#xff08;简称TS&#xff09;的基础上&#xff0c;扩展了声明式UI、状态管理等相应的能力&#xff0c;让开发者可以以更简洁、更自然的方式开发高性能应用。TS是JavaScript&#xff08;简称JS&#xff09;的超…

shiro的前后端分离模式

shiro的前后端分离模式 前言&#xff1a;在上一篇《shiro的简单认证和授权》中介绍了shiro的搭建&#xff0c;默认情况下&#xff0c;shiro是通过设置cookie&#xff0c;使前端请求带有“JSESSION”cookie&#xff0c;后端通过获取该cookie判断用户是否登录以及授权。但是在前…

【开源】基于Vue和SpringBoot的木马文件检测系统

项目编号&#xff1a; S 041 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S041&#xff0c;文末获取源码。} 项目编号&#xff1a;S041&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 木马分类模块2.3 木…

JavaScript 表达式

JavaScript 表达式 目录 JavaScript 表达式 一、赋值表达式 二、算术表达式 三、布尔表达式 四、字符串表达式 表达式是一个语句的集合&#xff0c;计算结果是个单一值。 在JavaScript中&#xff0c;常见的表达式有4种&#xff1a; &#xff08;1&#xff09;赋值表达式…

Postman接口自动化测试之——批量参数化(参数文件)

接口请求中的参数引用格式&#xff1a;{{参数名}} 参数文件只适用于集合中。 创建参数文件 以记事本举例&#xff0c;也可以使用其他编辑器&#xff1b;第一行参数名&#xff0c;用半角逗号&#xff08;英文逗号&#xff09;隔开&#xff0c;第二行为参数值&#xff0c;一样…

栈详解(C语言)

文章目录 写在前面1 栈的定义2 栈的初始化3 数据入栈4 数据出栈5 获取栈顶元素6 获取栈元素个数7 判断栈是否为空8 栈的销毁 写在前面 本片文章详细介绍了另外两种存储逻辑关系为 “一对一” 的数据结构——栈和队列中的栈&#xff0c;并使用C语言实现了数组栈。 栈C语言实现源…

Java基于springoot开发的企业招聘求职网站

演示视频&#xff1a; https://www.bilibili.com/video/BV1xw411n7Tu/?share_sourcecopy_web&vd_source11344bb73ef9b33550b8202d07ae139b 技术&#xff1a;springootmysqlvuejsbootstrappoi制作word模板 主要功能&#xff1a;求职者可以注册发布简历&#xff0c;选择简…

Redis面试题:redis做为缓存,mysql的数据如何与redis进行同步呢?(双写一致性)

目录 强一致性&#xff1a;延迟双删&#xff0c;读写锁。 弱一致性&#xff1a;使用MQ或者canal实现异步通知 面试官&#xff1a;redis做为缓存&#xff0c;mysql的数据如何与redis进行同步呢&#xff1f;&#xff08;双写一致性&#xff09; 候选人&#xff1a;嗯&#xff…