C++基础知识快速入门

news2024/9/29 0:00:32

目录

一, 命名空间

1.1命名空间使用命名空间中成员该如何使用呢?

1.2  命名空间其他2种使用方式:

1. using 将其中一个成员引入

2. using namespace 

二,C++输入&输出 (简单运用)

2. 1 头文件

2. 2 cout 与 cin 的特性及简单应用:

 三,缺省参数

 3. 1 概念

 3. 2缺省参数的分类:

 3. 3  特性注意

 四,函数重载

4. 1概念

4. 2行参列表分类

1. 参数不同

2. 类型不同

3. 类型顺序

 4.3 为什么C不支持,而C++支持重载呢?

五, 引用

 5.1 概念 

 5.2 引用特性

 5.2 使用场景

1. 做参数

2. 做返回值

5. 3 传参,与传引用效率比较

5.4 常引用

六, 内联函数  

6.1 特性


一, 命名空间

    在C/C++中,变量、函数和后面要学到的类都是大量存在的,这些变量、函数和类的名称将都存 在于全局作用域中,可能会导致很多冲突。使用命名空间的目的是对标识符的名称进行本地化以避免命名冲突或名字污染namespace关键字的出现就是针对这种问题的。
#include <stdio.h>
#include<stdlib.h>

int rand = 0;

namespace set  // 看起来有些类似于结构体,但不是结构体创建的是类型;
{
   int rand = 0;
}
int main()
{
	printf("%d\n", rand); 
    
// 运行这段代码我们会发现:rand重定义
// 原因是:预处理时会加载stdlib.h头文件代码,里面存有rand函数。
// 解决方法:1. 在C语言中我们只能改名字。
//           2. 在c++中我们可以在全局域建立命名空间,存放变量,这样就不与头文件中的名冲突。
// 使用如下:
    printf("%d\n", set::rand);
	return 0;
}

(注意:命名空间都在全局变量域定义,生命周期同静态区相同。命名空间只是改变了编译器找他的规则。) 

1.1命名空间使用命名空间中成员该如何使用呢?

比如 :

  • 1. 可以定义变量/函数/类型 。
  • 2. 命名空间可以嵌套使用。
  • 3. 不同文件之间,相同的命名空间将会被整合。

代码举例如下: 

namespace set
{
 // 1. 命名空间中可以定义变量/函数/类型
   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;
 }
}


1.2  命名空间其他2种使用方式:

  • 1. using 将其中一个成员引入

using N::b ;
int main ()
{
    printf ( "%d\n" , N::a );   
    printf ( "%d\n" , b );
    return 0 ;    
}
  • 2. using namespace + xxx   将整个命名空间引入 (慎用--会让隔离失效导致重命名

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

二,C++输入&输出 (简单运用)

2. 1 头文件

#include<iostream>           // 早期编译器是为#include<iostream.h>  ,如今编译器不支持这种写法了。
using  namespace  std;     // 如果不做处理每次输入输出都得 std::cout, std::cin, std::endl 这样写不方便,所以直接一次性引入

但这种写法在大项目中不太合适,容易出现命名冲突 ,较好的写法是仅对这2个单独引入,如下:

#include<iostream>

using  std::cout;

using  std::cin;

// 这样就能避免其他方法引入

2. 2 cout 与 cin 的特性及简单应用:

  • 1. 使用cout标准输出对象(控制台)cin标准输入对象(键盘)时,必须包含< iostream >头文件 以及按命名空间使用方法使用std。
  • 2. cout和cin是全局的流对象,endl是特殊的C++符号,表示换行输出,他们都包含在包含< iostream >头文件中。
  • 3. <<是流插入运算符,>>是流提取运算符
  • 4. 使用C++输入输出更方便,不需要像printf/scanf输入输出时那样,需要手动控制格式。 C++的输入输出可以自动识别变量类型
  • 5. 实际上cout和cin分别是ostream和istream类型的对象,>>和<<也涉及运算符重载等知识, 这里只是简单学习他们的使用。
#include<iostream>
using namespace std;
int main()
{   
	int k = 10;
	int c;
	double z;
	// 1. cout
	printf("%d\n", k); // C++向下兼容C
	cout << "hello word"<< " " << k << endl;  // endl 其实等同于插入“\n”
	cout << "hello word" << " " << k << "\n";
	// 2. endl
	cin >> k >> c >> z;
	cout << k << " " << c << " " << z;
	return 0;
}

 三,缺省参数

3. 1 概念

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

 

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

 3. 2缺省参数的分类:

  • 1. 全缺省参数
  • 2. 半缺省参数
void Func(int a = 0, int b = 4, int z = 6)
{
	cout << a << endl;
}
int main()
{
	Func(); // 缺少全部参数----全缺参数
	Func(1); //缺少部分参数----半缺参数
	Func(, 7, );   //  该代码会报错,可见缺省参数,也不是乱填的还得遵循一些规则
	Func(, 5, 7);  //  报错
	return 0;
}

应用场景:就以游戏为例,移动默认键就可以理解为全缺省参数,当你修改为自己适应的键位时则理解为输入参数。 

 3. 3  特性注意

  • 1. 半缺省参数必须从右往左依次来给出,不能间隔着给。
  • 2. 缺省参数不能在函数声明和定义中同时出现。(缺省参数要么在声明中出现,要么在定义中出现,推荐在声明中设置)

如:

//a.h
  void Func(int a = 10);
  
// a.cpp
  void Func(int a = 20)
 {}
  
// 注意:如果生命与定义位置同时出现,恰巧两个位置提供的值不同,那编译器就无法确定到底该
// 用那个缺省值。----这里涉及函数重载,后面我们会了解

 四,函数重载

4. 1概念

自然语言中,一个词可以有多重含义,人们可以通过上下文来判断该词真实的含义,即该词被重载了。

函数重载:是函数的一种特殊情况,C++允许在同一作用域中声明几个功能类似的同名函数,这些同名函数的形参列表(参数个数类型类型顺序)不同,常用来处理实现功能类似数据类型不同的问题。(而C是不允许同名函数)

4. 2行参列表分类

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. 类型不同

// 2、参数个数不同
void f()
{
 cout << "f()" << endl;
}
void f(int a)
{
 cout << "f(int a)" << endl;
}

3. 类型顺序

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

 (值得注意的是, 缺省参数不同,则不满足重载函数的要求,当系统调用此函数时会发生歧义报错。)


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

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

int main()
{
	Func();
}
//  我们运行此代码就会发现会发生报错

 

 4.3 为什么C不支持,而C++支持重载呢?

      这里将运用到一些反汇编的知识,编译过程的知识。这里编译详细过程请移步这篇文章 适合小白学习预处理与程序环境,这篇文章就够了_花果山~~程序猿的博客-CSDN博客

     我们知道程序运行要经过预处理->编译->汇编->链接这几个过程,其中在会遇到定义在其他文件的情况等:

  • 1.   如果函数定义在本文件中,那么编译时就会填上函数地址。
  • 2.   如果只是声明,定义在其他文件中,那么编译不会填上地址,而是在链接时期通过函数修饰名去其他文件查找函数,如果有再填上地址。

     C++目标文件符号表中不是直接用函数名的标识来查找函数的,而函数名的修饰规则在不同编译器下是不同的,下面是在linux进行的。 

linux下,其函数的修饰名规则是:_Z + 函数名长度 + 函数名 + 形参首字母 

如下面代码:

// 在test.h中
void f();
void f(int a);

// 在test.c中
void f()
{
	printf("f()");
}

void f(int a)
{
	printf("f(int a)");
}

//  测试文件
int main()
{
	f();
	f(1);
	return 0;
}

C++程序在linux操作系统下,编译函数的反汇编如下:

 C语言不支持重载,因为函数修饰名区分度不够。在编译过程中,从其他文件查找,C语言是单纯查找函数名,所以函数重名则机器无法区分。

下面是在C语言下的反汇编:

因此,在C++中有了比较复杂的函数修饰名规则,只要形参不同,那么两个函数就不存在冲突,链接时调用函数查找地址也是明确的。

五, 引用

5.1 概念 

     引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间。

     类型& 引用变量名(对象名) = 引用实体;(注意:引用是与变量必须是同类型)

#include <iostream>
using std::cout;
using std::cin;
int main()
{
    int a = 10;
    int& b = a;
    cout << a << " " << b << "\n";
    return 0;
}

我们可以发现引用与被引用的变量地址相同 

 5.2 引用特性

  • 1. 引用在定义时必须初始化
  • 2. 一个变量可以有多个引用,(多个名字)
  • 3. 引用一旦引用一个实体,再不能引用其他实体。(凸显出指针就像个渣男)

 5.2 使用场景

1. 做参数

#include <iostream>
using std::cout;
using std::cin;
void swap(int& a, int& b)
{
	int tmp = b;
	b = a;
	a = tmp;
}

void j(int*& a)      // 传二级指针
{
	*a *= 2;   // 引用就是一级指针本体
}

int main()
{
	int a = 10, b = 20;
	swap(a, b);

	int z = 100;
	int* k = &z;
	j(k);     
	cout << z;
	return 0;
}

2. 做返回值

#include <iostream>
using std::cout;
using std::cin;

int func(int& a, int& b)
{
	int c = a + b;
	return c;   // 这是将c的值进行临时拷贝(一般放在寄存器中)
}

int& func2(int& a, int& b)
{
	int c = 2 * a + b;
	return c;   // 返回一个引用,出函数后通过引用再次访问(本质上是非法访问)
}

int main()
{
	int a = 1, b = 2;
	int& a1 = a, & b1 = b;
	int z = func(a1, b1);
	cout << z << "\n";
	z = func2(a1, b1);
	cout << z << "\n";
	return 0;
}

  

注意:如果函数返回时,出了函数作用域,如果返回对象还在(还没还给系统--比如:静态区,堆区的数据),则可以使用引用返回,如果已经还给系统了(比如:在函数栈桢上的局部变量),则必须使用传值返回。

5. 3 传参,与传引用效率比较

    这里有一段测试程序,分别测试函数传参两种方式。

#include <time.h>
struct A{ int a[10000]; };
void TestFunc1(A a){
  
}

void TestFunc2(A& a){
  
}

void TestRefAndValue()
{
 A a;
 // 以值作为函数参数
 size_t begin1 = clock();
 for (size_t i = 0; i < 10000; ++i)
 TestFunc1(a);
 size_t end1 = clock();
 // 以引用作为函数参数
 size_t begin2 = clock();
 for (size_t i = 0; i < 10000; ++i)
 TestFunc2(a);
 size_t end2 = clock();
// 分别计算两个函数运行结束后的时间
 cout << "TestFunc1(A)-time:" << end1 - begin1 << endl;
 cout << "TestFunc2(A&)-time:" << end2 - begin2 << endl;
}

可见,传参时,传引用速率快于传值;传返回值时,传引用也快于传值

 5.4 常引用

    这里涉及数据权限的问题

void f()
{
	// 扩大权限
	const int a = 10;  // 这里a只读
	//int& a1 = a;       // 而引用a, 可以读和写,属于是扩大权限,会报错是不允许的。
	const int& a1 = a; // 设置a1 只读
	
	// 缩小权限
	int b = 20;        // 这里b允许 读于写
	const int& b1 = b;  // 被允许是因为只是缩小权限
}

非const修饰的引用初始化时,对象得是变量,否则就是权限放大。

常见的常量有:  

1. 被const修饰的变量。

 const  int  a = 10;

const  int&  a1 = a;  

2. 临时变量,如:函数返回值, 表达式

 const  int&  k =  3 + 4;   // 会创建一个临时变量储存

 const int&  z = 1.111;    // int截断值放在临时变量中

// int& k = 3 + 4;  不被允许

5.5  引用和指针的区别  

  •      在语法概念上引用就是一个别名,没有独立空间,和其引用实体共用同一块空间。 
  •      在底层实现上实际是有空间的,因为引用是按照指针方式来实现的。

我们查看下面代码的反汇编,

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

可见,引用在底层实现上实际是有空间的,因为引用是按照指针方式来实现的,不能说相同,只能说一模一样。

 

 5.6 引用与指针的不同点

1. 引用概念上定义一个变量的别名,指针存储一个变量地址。
2. 引用在定义时必须初始化,指针没有要求。
3. 引用在初始化时引用一个实体后,就不能再引用其他实体,而指针可以在任何时候指向任何
一个同类型实体
4. 没有NULL引用,但有NULL指针
5. 在sizeof中含义不同引用结果为引用类型的大小,但指针始终是地址空间所占字节个数(32 位平台下占4个字节)
6. 引用自加即引用的实体增加1,指针自加即指针向后偏移一个类型的大小
7. 有多级指针,但是没有多级引用
8. 访问实体方式不同,指针需要显式解引用,引用编译器自己处理
9. 引用比指针使用起来相对更安全

 


 

六, 内联函数  

      inline修饰的函数叫做内联函数,编译时C++编译器会在调用内联函数的地方展开,没有函数调用建立栈帧的开销,内联函数提升程序运行的效率。

      

6.1 特性

  • 1. inline是一种以空间换时间的做法,如果编译器将函数当成内联函数处理,在编译阶段,会用函数体替换函数调用,缺陷:可能会使目标文件变大,优势:少了调用开销,提高程序运行效率。
  • 2. inline对于编译器而言只是一个建议,不同编译器关于inline实现机制可能不同,一般建议:将函数规模较小(即函数不是很长,具体没有准确的说法,取决于编译器内部实现)、递归、且频繁调用的函数采用inline修饰,否则编译器会忽略inline特性。
  • 3. inline不建议声明和定义分离,分离会导致链接错误。因为inline被展开,就没有函数地址了,链接就会找不到,如下:
// 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 中被引用

【面试题】
宏的优缺点?
优点:
1.增强代码的复用性。
2.提高性能。
缺点:
1.不方便调试宏。(因为预编译阶段进行了替换)
2.导致代码可读性差,可维护性差,容易误用。
3.没有类型安全的检查 。
C++有哪些技术替代宏
1. 常量定义 换用const enum
2. 短小函数定义换用内联函数

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

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

相关文章

2023年软件测试常见面试题100%问必背全套教程

随着数字化时代的到来&#xff0c;软件测试越来越受到重视。在未来的几年里&#xff0c;软件测试将继续成为信息技术领域中的热门职业之一。如果你是一名正在寻找或准备进入软件测试行业的人&#xff0c;那么这套常见面试题全套教程对你来说会非常有用。 这套教程旨在帮助你了…

MySQL主从同步配置

Mysql 主从同步原理 就是基于数据库里面的那个 binlog 文件进行数据同步 具体步骤&#xff1a; step1&#xff1a;master将数据改变记录到二进制日志&#xff08;binary log&#xff09;中。step2&#xff1a; 当slave上执行 start slave 命令之后&#xff0c;slave会创建一个…

Unity 后处理(Post-Processing) -- (2)创建后处理配置文件

通过前面一小节&#xff0c;我们初步认识了后处理是什么&#xff0c;在Unity中简单的试了试后处理的效果。本节我们来创建一个我们自己的后处理配置文件&#xff08;post-processing profile&#xff09;。 一个后处理配置文件包含了一系列为了达到特定视觉效果的后处理效果的配…

C51 - DS18B20

Thermometer 1> 实验概述2> 硬件设计3> DS18B204> 单总线&#xff08;1-Wire&#xff09;通讯协议4.1> 复位时序4.2> 写-DS18B20时序4.3> 读-DS18B20时序4.4> 命令 5> 程序设计5.1> 编程思路5.2> 代码实现 6> 联调测试 1> 实验概述 实现…

Redis集合底层实现原理

目录 本章重点简单动态字符串SDS集合底层实现原理zipListlistPackskipListquickListKey 与Value中元素的数量 本章重点 掌握Redis简单动态字符串了解Redis集合底层实现原理 简单动态字符串SDS SDS简介 我们Redis中无论是key还是value其数据类型都是字符串.我们Redis中的字符…

从入门到精通:30天速成黑客教程到底有多狠?

首先我谈下对黑客&网络安全的认知&#xff0c;其实最重要的是兴趣热爱&#xff0c;不同于网络安全工程师&#xff0c;他们大都是培训机构培训出来的&#xff0c;具备的基本都是防御和白帽子技能&#xff0c;他们绝大多数的人看的是工资&#xff0c;他们是为了就业而学习&am…

ShardingSphere学习笔记

目录 1. 概述 1.1 分库分表是什么 1.2 分库分表方式 1.2.1 垂直分表 1.2.2 垂直分库 1.2.3 水平分库 1.2.4 水平分表 1.3 小结 1.3 分库分表带来的问题 1.3.1 事务一致性问题 1.3.2 跨节点关联查询 1.3.3 跨节点分页、排序函数 1.3.4 主键避重 1.3.5 公共表 2. …

JavaSE基础(二)—— 类型转换、运算符、键盘录入

目录 一、类型转换 1. 自动类型转换 1.1 自动类型转换的底层原理&#xff1a; ​1.2 自动类型转换的其他形式​编辑 2. 表达式的自动类型转换 3. 强制类型转换 3.1 强制类型转换底层原理​编辑 3.2 注意事项 二、运算符 1. 算数运算符 1.1 案例&#xff1a;数值拆分…

【群智能算法】一种改进的哈里斯鹰优化算法 IHHO算法[1]【Matlab代码#17】

文章目录 1. 原始HHO算法2. 改进的哈里斯鹰优化算法2.1 动态自适应逃逸能量E2.2 拉普拉斯交叉算子2.3 动态自适应权重 3. 部分代码展示4. 仿真图展示5. 资源获取 1. 原始HHO算法 详细介绍此处略&#xff0c;可参考HHO算法介绍 2. 改进的哈里斯鹰优化算法 2.1 动态自适应逃逸…

【算法】刷题中的位运算

作者&#xff1a;指针不指南吗 专栏&#xff1a;算法篇 &#x1f43e;人类做题的过程&#xff0c;其实是暴搜的过程&#x1f43e; 文章目录 1.位运算概述2.位运算符3.位运算应用3.1整数的奇偶性判断3.2有关 2 的幂的应用3.3lowbit(x)返回x的最后一位13.4二进制数中1的个数3.5求…

6.S081——陷阱部分(一篇读懂Xv6系统调用)——xv6源码完全解析系列(5)

0.briefly speaking 这篇博客将要开始尝试阅读和研究与Xv6陷阱机制相关的代码&#xff0c;主要有以下文件&#xff0c;最重要的是结合Xv6 book将Xv6处理陷阱的相关逻辑和流程弄透。在Xv6的语境中所谓陷阱的触发有以下三种情况&#xff1a; 系统调用严重错误&#xff08;比如除…

设备仪器仪表盘读数识别算法 yolov5

设备仪器仪表盘读数识别系统基于YoLov5网络模型分析技术&#xff0c;设备仪器仪表盘读数识别算法模型自动识别指针型仪表读数。Yolo算法采用一个单独的CNN模型实现end-to-end的目标检测&#xff0c;核心思想就是利用整张图作为网络的输入&#xff0c;直接在输出层回归 bounding…

【Maven笔记2】Maven安装与配置

1、前置准备 maven是使用Java语言进行开发的&#xff0c;因此在安装maven之前&#xff0c;先需要有java运行环境。如何确认本机是否安装了JDK环境呢&#xff1f;打开终端运行如下命令&#xff1a; java -version如下图显示说明已经安装了JDK环境。 备注&#xff1a;如何安装J…

Intel Xeon(Ice Lake) Platinum 8369B阿里云CPU处理器

阿里云服务器CPU处理器Intel Xeon(Ice Lake) Platinum 8369B&#xff0c;基频2.7 GHz&#xff0c;全核睿频3.5 GHz&#xff0c;计算性能稳定。目前阿里云第七代云服务器ECS计算型c7、ECS通用型g7、内存型r7等规格均采用该款CPU。 Intel Xeon(Ice Lake) Platinum 8369B Intel …

OSI七层网络参考模型

七层模型的诞生 深夜中&#xff0c;在一家美国酒吧坐着几个正在谈论迪斯尼电影里的7个小矮人&#xff0c;他们把小矮人的名字写在餐巾纸上&#xff0c;有人开玩笑说7对于网络分层是个好数字&#xff0c;这几个人就是制定OSI标准小组的成员&#xff0c;后来OSI真的就设计成了七…

TensorFlow入门图像分类-猫狗分类-MobileNet优化

在上一篇文章中《Tensorflow入门图像分类-猫狗分类-安卓》&#xff0c;介绍了使用TensorFlow训练一个猫狗图像分类器的模型并在安卓应用上使用的全过程。 在这一篇文章中&#xff0c;将采用 MobileNet 来重新训练一个猫狗图像分类器。 一、 MobileNet 介绍 MobileNet是一种轻量…

服务(第十六篇)mysql①基础

什么是数据库&#xff1f; 数据&#xff1a; ①描述事物的符号记录称为数据&#xff08;Data&#xff09;&#xff0c;数字、文字、图形、图像、声音、档案记录等&#xff1b; ②数据是以“记录”的形式按照统一的格式进行存储的&#xff0c;而不是杂乱无章的。 行&#xf…

35岁以10亿美元身价登上《财富》杂志亿万富豪榜的电商传奇谢家华

Zappos的介绍 Zappos可谓是电商的传奇&#xff0c;国内同类电商是乐淘。Zappos是一家在线卖鞋和服装的公司&#xff0c;1999年创立&#xff0c;2009年被亚马逊以12亿元收购&#xff0c; 多次入选财富杂志最佳雇主公司top100。 Zappos的创始人及CEO 提到Zappos就不得不介绍下…

SQL知识汇总

什么时候用存储过程合适 当一个事务涉及到多个SQL语句时或者涉及到对多个表的操作时就要考虑用存储过程&#xff1b;当在一个事务的完成需要很复杂的商业逻辑时&#xff08;比如&#xff0c;对多个数据的操作&#xff0c;对多个状态的判断更改等&#xff09;要考虑&#xff1b…

05.rabbitMQ之搭建的各种坑

1.持久化需要重新设置队列 2.异步发布确认的坑, 生产者发消息太快只会确认最大的编号 1.消费者还是要确认消息 channel.basicAck(message.getEnvelope().getDeliveryTag(), false); 因为你发送的太快了&#xff0c;只会返回成功接收的最大的编号 3.消费者消息堆积(开启了消息手…