C++ 入门

news2024/11/18 9:43:22

C++是在C的基础之上,容纳进去了面向对象编程思想,并增加了许多有用的库,以及编程范式等

文章目录

  • 一、命名空间
  • 二、输入输出
  • 三、缺省参数
  • 四、函数重载
  • 五、引用
    • 1. 引用的用法
    • 2. 常引用
    • 3. 引用的使用场景
    • 4. 引用的底层实现
  • 六、内联函数
  • 七、auto 关键字(C++11)
  • 八、范围 for -- 语法糖(C++11)
  • 九、nullptr(C++11)

C++ 为了解决 C语言中存在的一些不好的地方,从而增加了一些语法

一、命名空间

在项目组中,进行代码合并时,可能会遇到自己和其他人写的代码,定义了相同的名字,发生命名冲突,在C语言中,只能在产生错误后,修改名字,没有很好的预防手段

在这里插入图片描述

自己定义的变量名,函数名,类型名等,都可能会和别人定义的名字冲突,或者和库的名字冲突,因为此时相同的名字处在同一个域(全局域)

而在不同的域定义了相同的名字,并不会产生命名冲突,使用时是局部优先

C++ 中增加了另一种新的域,叫做命名空间,用 namespace 关键字定义

命名空间定义:
namespace 空间名
{
	//类型,变量,函数等
	
}	//花括号后没有分号

将处在全局域中的变量,函数,类型等,封装在命名空间域中,便可以防止命名冲突
在这里插入图片描述

在命名空间域中也包含全局域和局部域,因此不会影响变量的生命周期

在命名空间域中,内部对内部的访问,也是遵守先声明后使用,优先使用局部,然后使用命名空间域中的全局,最后使用命名空间域外的全局

命名空间域会影响编译时期的查找规则在查找一个变量、函数、类型是否定义时,默认是在局部找(代码块内),局部不存在便会去全局找,全局找不到便会报错,不会直接去已经定义的命名空间中找

外部想要访问命名空间内部的内容时:有三种方法

  • 指定命名空间访问,使用域作用限定符 :: (两个冒号)
  • 展开命名空间中的所有内容,using namespace 命名空间名
  • 展开命名空间中的常用内容,using 命名空间名 :: 内容

C++ 中,将标准库函数的代码放在 iostream 头文件中,并用 std 命名空间封装,防止用户和库中的命名冲突,这里以 cout 为例

//指定命名空间访问
//:: 域作用限定符,左边为空,代表在全局域中查找
#include <iostream>

int main()
{
	std::cout << "hello world";
	
	return 0;
}

//展开命名空间中的所有内容
#include <iostream>

using namespace std;

int main()
{
	cout << "hello world";

	return 0;
}

//展开命名空间中的常用内容
#include <iostream>

using std::cout;

int main()
{
	cout << "hello world";

	return 0;
}

平时练习时可以使用全部展开,写项目时建议展开常用的和指定访问

还需要注意几点

  • 命名空间的名字相同时,会合并为一个命名空间,但是名字相同的命名空间中,如果存在相同的定义会报错
  • 命名空间可以定义在命名空间中,即命名空间可以嵌套定义

二、输入输出

C++ 中标准库提供的 cin 可以用于输入,cout 可以用于输出,cin 和 cout 自动识别类型,不用指定输入输出格式,cout 中 endl 表示换行

#include <iostream>

//为了可以找到封装在 std 中的 cin 和 cout
using namespace std;

int main()
{
    char c;
    int i;
    double d;

	//自动识别类型,cin >> 可以简单理解为数据从控制台流向变量
    cin >> c >> i >> d;
    
    //自动识别类型,输出数据后换行,cout << 可以简单理解为数据从变量流向控制台
    cout << c << endl;
    cout << i << endl;
    cout << d << endl;
    cout << "hello C++" << endl;
    
    return 0;
}

三、缺省参数

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

声明或定义函数时只能从右往左连续的为函数的参数指定缺省值,调用函数传参时,也只能从右往左连续省略实参

#include <iostream>

using namespace std;

//只能从右往左连续的为函数的参数指定缺省值
//void f1(int a, int b = 3, int c) -- 错误写法
void f1(int a, int b = 3, int c = 10)
{
    cout << a << " ";
    cout << b << " ";
    cout << c << endl;
}

int main()
{
    //只能从右往左连续省略实参
    //f1(1, , 3); -- 错误写法
    f1(1);
    f1(1, 2);
    f1(1, 2, 3);

    return  0;
}

注意:

  • 有缺省参数时,声明和定义不能同时给缺省参数,推荐在声明给,如果出现声明和定义分离(多文件时),只能在声明给,定义时不给
  • 缺省值只能是常量或全局变量(一般不使用全局变量)
//报错:非法将局部变量作为缺省参数
void f1(int a, int b = a)
{
	cout << a << endl;
}

四、函数重载

C++ 允许 在同一作用域中 声明几个功能类似的 同名函数,但是需要满足这些同名函数的形参列表(参数个数 或 参数类型 或 参数类型顺序)不同,常用来处理实现功能类似,但参数的数据类型不同的问题

#include <iostream>

using namespace std;

//参数个数不同
void f1()
{
	cout << "f1()" << endl;
}

void f1(int a)
{
	cout << "f1(int a)" << endl;
}

//参数类型不同
int Add(int A, int B)
{
	return A + B;
}

double Add(double A, double B)
{
	return A + B;
}

//类型顺序不同
void f2(int i, char c)
{
	cout << "f2(int i, char c)" << endl;
}

void f2(char c, int i)
{
	cout << "f2(char c, int i)" << endl;
}

int main()
{
	//参数个数不同
	f1();
	f1(1);

	//参数类型不同
	cout << Add(1, 2) << endl;
	cout << Add(1.1, 2.2) << endl;

	//参数顺序不同
	f2(1, 'a');
	f2('a', 1);

	return 0;
}

未重载的函数,调用函数传参类型不同时,会隐式转换

重载的函数,调用函数时,实参的参数列表所有重载的函数的参数列表 都不匹配时,不会隐式转换,编译器无法分辨调用哪个函数,便会报错

C++ 函数重载的原理 – 对函数名修饰
以 Linux 下的 gcc/g++函数名修饰规则为例

用 gcc 编译 .c 文件后,用 objdump -S 可执行程序 指令,查看函数名修饰规则
在这里插入图片描述
用 g++ 编译 .cpp 文件后,用 objdump -S 可执行程序 指令,查看函数名修饰规则
在这里插入图片描述
在编译时期对函数名进行修饰之后,便可以根据调用函数时给的参数类型,确定函数调用的是哪个重载函数,因此重载函数只会影响编译速度

函数调用时,返回值可以选择性的使用,因此只有返回值不同的同名函数,调用时无法区分,便不能构成重载

五、引用

1. 引用的用法

//定义引用
//类型& 引用名 = 引用实体;
int a = 10;
int& ra = a;

在使用上:引用不是定义新变量,而是给指定的变量取别名,和该变量共用同一块空间

在这里插入图片描述

#include <iostream>

using namespace std;

int main()
{
	//定义变量 i
	int i = 0;
	
	//定义新变量 j, i 和 j 占用不同的空间
	int j = i;
	
	//给变量 i 取别名, i 和 k 占用相同的空间
	int& k = i;
	
	//i 和 j 的地址不同
	//i 和 k 的地址相同
	cout << &i << " ";
	cout << &j << " ";
	cout << &k << endl;
	
	++i;
	++j;
	++k;
	
	//结果为 2 1 2
	cout << i << " ";
	cout << j << " ";
	cout << k << endl;

	return 0;
}

注意

  • 引用是变量的别名
  • 引用在定义时必须初始化
  • 变量可以有多个引用,可以给引用初始化为变量的别名(给别名取别名,都是同一个变量)
  • 引用指定实体后,不能在引用其他实体
  • 没有 NULL 引用
  • 在 sizeof 中,引用结果为引用类型大小
  • 没有多级引用,引用指针,引用数组,可以按以下内容理解
    引用不需要开辟新空间,没有引用的引用
    引用不需要开辟新空间,没有引用的指针
    引用不需要开辟新空间,不能作为数组元素(数组元素有空间),即不存在引用数组

2. 常引用

C++ 中,指针和引用在使用时,权限只能保持或缩小,但是 权限不能放大

先以指针为例:

#include <iostream>

using namespace std;

int main()
{
	//指针权限放大 - error
	//i 是常变量,不可以被修改
	//int* 可以通过解引用修改变量的值
	//不可以修改 --> 可以修改 权限放大(不允许)
	const int i = 0;
	int* pi = &i;	//报错,const int* 无法转换为 int*

	//指针权限保持
	//i 是常变量,不可以被修改
	//const 修饰 *pi,因此 pi 不能通过解引用修改变量 i 的值
	//不可以修改 --> 不可以修改 权限保持
	const int i = 0;
	const int* pi = &i;

	//指针权限缩小
	//i 是变量,可以被修改
	//const 修饰 *pi,因此 pi 不能通过解引用修改变量 i 的值
	//可以修改 --> 不可以修改 权限缩小
	int i = 0;
	const int* pi = &i;

	return 0;
}

引用也是如此:

#include <iostream>

using namespace std;

int main()
{
	//引用权限放大 - error
	const int i = 0;
	int& ri = i;	//报错,const int 无法转换为 int&

	int& r = 10;	//报错

	//引用权限保持
	const int i = 0;
	const int& ri = i;

	const int& r = 10;

	//引用权限缩小
	int i = 0;
	const int& ri = i;

	return 0;
}

3. 引用的使用场景

(1) 输出型参数:

#include <iostream>

using namespace std;

//引用做参数,可以直接修改实参的值
void Swap(int& r1, int& r2)
{
    int tmp = r1;
    r1 = r2;
    r2 = tmp;
}

int main()
{
    int a = 10, b = 20;
  
    cout << a << " " << b << endl;

	//直接传变量 a 和 b;
    Swap(a, b);

    cout << a << " " << b << endl;

    return 0;
}

输出:
10 20
20 10

(2) 返回值引用:

在函数栈帧的知识中,函数的返回值是通过临时变量返回的(为什么不能直接返回?因为函数调用结束,回到调用函数处时,被调用函数的栈帧已经还给操作系统了),如果返回值较小,则使用寄存器,如果返回值较大,则在调用函数的栈帧中开辟

下述代码中,变量 n 在静态区,当函数调用结束,回到调用函数的栈帧中时,变量 n 不会被销毁但是编译器还是会通过临时变量的方式带回返回值

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

int main()
{
	int ret = Count();
	return 0;
}

此时程序员可以自行调整代码,将返回值设置为引用,便不会使用临时变量,而是使用原空间的别名

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

int main()
{
	int ret = Count();
	return 0;
}

注意:不要返回当前函数栈帧中的变量的引用

#include <iostream>

using namespace std;

int& Add(int a, int b)
{
	int c = a + b;
	
	return c;
}

int main()
{
	int& ret = Add(1, 2);

	//ret 的结果是随机值
	cout << "Add(1, 2) is :" << ret << endl;

	return 0;
}

什么情况下可以返回引用:调用函数结束,回到调用函数处时,变量不会销毁的,都可以做为引用返回
如:在堆上开辟的空间,静态区,参数中的引用等

引用做返回值时,’ 可以对函数的返回值进行修改 ',在之后学习的运算符重载中作用很大

传引用明显的比传值效率高
参数传值时,形参是实参的临时拷贝,返回值传值时,使用的是临时变量
参数传引用时,形参是实参的别名,返回值传引用时,使用的是变量的别名

4. 引用的底层实现

实现上:引用是由指针实现的,也是需要开辟空间的,虽然实现上是这样,但是为了便于使用引用,还是以使用上的概念为主

int main()
{
	int a = 0;

	//实现上,将 a 的地址赋给指针 ra
	int& ra = a;

	//实现上,编译器默认将 ra 解释为(*ra)
	//因此,&ra 解释为 &(*ra) == &a 所以 &a 和 &ra 的地址一样
	ra = 10;

	int* pa = &a;
	*pa = 10;

	return 0;
}

//启动调式,右键进入反汇编
	int a = 0;
00007FF71DA317AD  mov         dword ptr [a],0  

//引用和指针的指令,在汇编层面一模一样
	int& ra = a;
00007FF71DA317B4  lea         rax,[a]  
00007FF71DA317B8  mov         qword ptr [ra],rax  
	ra = 10;
00007FF71DA317BC  mov         rax,qword ptr [ra]  
00007FF71DA317C0  mov         dword ptr [rax],0Ah  

	int* pa = &a;
00007FF71DA317C6  lea         rax,[a]  
00007FF71DA317CA  mov         qword ptr [pa],rax  
	*pa = 10;
00007FF71DA317CE  mov         rax,qword ptr [pa]  
00007FF71DA317D2  mov         dword ptr [rax],0Ah

引用类型必须和引用实体是同种类型的,不同类型无法直接赋值,但可以通过以下两种方式

在 C/C++ 中,显示/隐式类型转换是通过临时变量来完成的,临时变量具有常属性(不可以被修改)

#include <iostream>

using namespace std;

int main()
{	
	int a = 2;
	double& ra1 = (double&)a;
	const double& ra2 = a;

	//输出 2 -9.25596e+61 2
	cout << a << " " << ra1 << " " << ra2 << endl;

	return 0;
}

//启动调式,右键进入反汇编
	int a = 2;
00007FF7780D23CD  mov         dword ptr [a],2  
//mov 将 2 放到 a 中

	double& ra1 = (double&)a;
00007FF7780D23D4  lea         rax,[a]  
00007FF7780D23D8  mov         qword ptr [ra1],rax 
//lea 取出 a 的地址放到 rax
//mov 将 rax 中的内容放到指针 ra1 中

	const double& ra2 = a;
00007FF7780D23DC  cvtsi2sd    xmm0,dword ptr [a]  
00007FF7780D23E1  movsd       mmword ptr [rbp+68h],xmm0  
00007FF7780D23E6  lea         rax,[rbp+68h]  
00007FF7780D23EA  mov         qword ptr [ra2],rax  
//cvtsi2sd 取出 a 中低 64 位,将其转换为浮点数,放到 xmm0
//movsd 将 xmm0 放到临时变量 rdb+68h(h 表示十六进制) 空间中
//lea 取出 rdb+68h 空间的地址放到 rax
//mov 将 rax 中的内容放到指针 ra2 中

引用 ra1 是 a 的别名,因此 ra1 会以浮点数的方式看待 a 中的值(这里可以修改 ra1,存在问题,待以后解决)
引用 ra2 是赋值时隐式转换过程中 临时变量的别名,因此 ra2 是以浮点数的方式看待浮点类型的临时变量的值

引用比指针使用起来更安全

六、内联函数

在 C语言中,宏的缺点:1. 不能调试 2. 没有类型检查 3. 有些场景下非常复杂,容易出错,宏的优点:1. 速度快(不用创建函数栈帧) 2. 类型不固定

在 C++ 中,为了弥补宏的缺点,推荐 用 const 和 enum 代替 宏常量,用 内联函数 代替 宏函数

用 inline 修饰的函数称作内联函数(可以调试,有类型检查,书写和函数一样容易记忆),编译时 C++ 编译器会 在调用内联函数的地方展开(速度快),

为了可以在 debug 模式观察到内联函数的展开,需要对编译器进行设置(因为 debug 模式下,编译器默认不会对代码进行优化)
在 vs 2022 中
右击项目 -> 属性 -> C/C++ 下的常规 -> 调式信息格式 改为 程序数据库 (/Zi)
右击项目 -> 属性 -> C/C++ 下的优化 -> 内联函数扩展 改为 只适用于 __inline (/Ob1)

#include <iostream>

using namespace std;

//内联函数
inline void Swap(int& a, int& b)
{
	int tmp = a;
	a = b;
	b = tmp;
}

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

	cout << a << " " << endl;

	return 0;
}

//启动调式,右键进入反汇编
//汇编指令中,函数调用时需要通过 call 指令,跳转到函数地址
//Swap 调用时的汇编指令中没有 call,也就说明内联函数展开了
	Swap(a, b);
00007FF64AB41552  mov         eax,dword ptr [a]  
00007FF64AB41556  mov         dword ptr [rsp+60h],eax  
00007FF64AB4155A  mov         eax,dword ptr [b]  
00007FF64AB4155E  mov         dword ptr [a],eax  
00007FF64AB41562  mov         eax,dword ptr [rsp+60h]  
00007FF64AB41566  mov         dword ptr [b],eax  

内联函数特性:

  • 函数用 inline 修饰,对编译器而言只是一个建议,在编译阶段是否会展开,取决于编译器,不加 inline 修饰的函数不会展开
    建议 将函数规模小,不是递归并且频繁调用的函数 用 inline 修饰,否则编译器会忽略 inline 特性
  • 内联函数是一种以空间换时间的方法
    优点:少了函数调用开销,提升效
    缺点:可执行程序变大
  • 内联函数如果声明和定义分离,会导致链接错误
    编译时会将 F.h 中的声明拷贝到 test.cpp 中,此时 test.cpp 中只有内联函数 f 的声明,没有内联函数 f 的定义,于是便无法将 f 函数展开(.cpp 文件是单独编译的),并且由于内联函数会展开,所以内联函数 f 并不会在 test.cpp 的符号表中产生,也就导致在链接时合并符号表后无法找到函数 f

    书写内联函数时,在 .h 文件中 定义

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

在早期的 C/C++ 中 auto 用来表示变量具有自动存储器的局部变量(但是一直没有人使用 auto)

到了 C++11,标准委员会赋予了 auto 全新的含义,auto 不再是一个存储类型指示符,而是一个新的类型指示符(为了避免与 C++98 中的 auto 发生混淆,C++11 只保留了 auto 作为类型指示符的用法)

auto 声明的变量,由编译器在编译时期 根据初始化的值的类型 自动推到变量的类型

#include <iostream>

using namespace std;

int main()
{
	//auto 声明的变量必须初识化
	//auto a; --error

	//auto 自动推导变量类型
	auto c = 'a';
	auto i = 10;
	auto d = 3.14;

	//auto 声明指针时 auto 和 auto* 没有区别,但 auto* 一定要初识化为地址
	auto p1 = &i;
	auto* p2 = &i;

	//引用类型必须用 auto&
	auto& r = i;

	//typeid 是操作符,typeid(变量).name() 获取变量的类型
	//输出:char int double int * __ptr64 int * __ptr64 int
	cout << typeid(c).name() << " ";
	cout << typeid(i).name() << " ";
	cout << typeid(d).name() << " ";
	cout << typeid(p1).name() << " ";
	cout << typeid(p2).name() << " ";
	cout << typeid(r).name() << endl;
	
	return 0;
}

auto 不是一种 “类型” 的声明,而是一种类型声明时的 “占位符”,编译器在编译期会将 auto 替换为变量实际的类型,所以 auto 声明多个变量时,编译器只会对第一个变量的类型进行推导,然后将 auto 替换为推导的类型,因此每个变量的类型应该相同(不相同会编译错误)

auto 不能作为函数的参数,因为编译时无法知道实参的类型

auto 不能用来声明数组

在以后的学习中,某些类型较长,容易写错,此时便可以使用 auto 关键字自动推导,这种情况下也可以使用 typedef 来解决,不过 typedef 在某些情况存在一些问题

typedef char* pstr;

int main()
{
	//编译报错,const 修饰 p1,需要指定初始化
	//const pstr p1;

	//const 修饰 p2,编译通过
	const pstr* p2;

	return 0;
}

八、范围 for – 语法糖(C++11)

C++11 中引入了基于范围的 for 循环

范围 for 循环后的括号由冒号 : 分为两部分
第一部分是范围内用于迭代的变量,第二部分则表示被迭代的范围。

#include <iostream>

using namespace std;

int main()
{
	int array[] = { 1, 2, 3, 4, 5, 6 };

	//自动将数组 array 中的元素依次赋值给 i,自动判断结束
	//i 是循环变量,auto 是循环变量的类型
	for (auto i : array)
	{
		cout << i << " ";
	}
	cout << endl;

	return 0;
}

注意:和普通循环一样,可以使用 continue 和 break

九、nullptr(C++11)

在定义指针变量时,如果不知道指针的指向,通常会将指针变量指向 NULL

在 C++98 中,NULL实际是一个宏,在传统的 C 头文件 stddef.h 中

//在 C++ 中,NULL 被定义成 0
//在 C 语言中,NULL 被定义成 ((void *)0)
#ifndef NULL
    #ifdef __cplusplus
        #define NULL 0
    #else
        #define NULL ((void *)0)
    #endif
#endif

由于在 C++98 中 NULL 被定义为了 0,在使用 NULL 时,难免会遇到一些麻烦

#include <iostream>
#include <stddef.h>

using namespace std;

void f(int a)
{
	cout << "f(int)" << endl;
}

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

int main()
{
	f(0);
	f(NULL);

	return 0;
}

输出:
f(int)
f(int)

程序本意是想通过 f(NULL) 调用指针版本的 f(int*) 函数,但是由于 NULL 被定义成 0,因此与程序的初衷相悖

C++11 中,引入了新的关键字 nullptr,表示指针空值((void*)0),sizeof(nullptr) 与 sizeof((void*)0)所占的字节数相同

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

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

相关文章

数组

循环队列中元素个数计算方法是固定的&#xff0c;即(尾-头)%长度&#xff0c;但是由于是循环队列所以尾可能会小于头&#xff0c;所以要加上长度&#xff0c;使尾-头保持是正整数&#xff0c;然后再对长度求余&#xff0c;即元素个数。循环队列中&#xff1a;头指针指向队列头元…

基于Java+Spring+Html的图书借阅管理系统详细设计和实现

博主介绍&#xff1a;✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专…

seo:百度统计

一、百度统计官网https://tongji.baidu.com/web5/welcome/login二、理解百度统计个人理解&#xff0c;添加这段代码到网站首页&#xff0c;有人访问该网站&#xff0c;即会加载这段代码&#xff0c;接着把信息发送到百度统计id 对应的百度统计账号&#xff0c;可从百度统计查看…

OpenMMLab AI实战课笔记 -- 第2节课

OpenMMLab AI实战课笔记 -- 第2节课1. 第二节课(图像分类)1.1 深度学习模型1.2 网络进化过程1.3 ResNet &#xff08;残差网络&#xff09;1.4 卷积的参数量1.5 卷积的计算量&#xff08;乘加次数&#xff09;1.6 降低模型参数量和计算量的方法1.7 可分离卷积1.8 注意力机制 At…

常见正则表达式使用参考

目录 一、正则函数 1.REGEXP 2.regexp_replace 3.regexp_extract 二、正则表达式 三、特殊字符转义 一、正则函数 1.REGEXP 语法格式&#xff1a; A REGEXP B &#xff08;A是需要匹配的字符串&#xff0c;B是正则表达式字符串&#xff09; 操作类型: strings 描述: …

UniTask详解

前言 UniTask为Unity提供一个高性能&#xff0c;0GC的async/await异步方案。 基于值类型的UniTask和自定义的 AsyncMethodBuilder 来实现0GC使所有 Unity 的 AsyncOperations 和 Coroutines 可等待基于 PlayerLoop 的任务( UniTask.Yield, UniTask.Delay, UniTask.DelayFrame…

哈工大机器学习复习笔记(四)

本篇文章是在参考西瓜书、PPT课件、网络上相关博客等资料的基础上整理出的机器学习复习笔记&#xff0c;希望能给大家的机器学习复习提供帮助。这篇笔记只是复习的一个参考&#xff0c;大家一定要结合书本、PPT来进行复习&#xff0c;有些公式的推导最好能够自己演算一遍。由于…

Scala 简单实现数据库连接池

在使用JDBC的时候&#xff0c;连接池是非常宝贵的资源。为了复用这些资源&#xff0c;可以将连接保存在一个队列中。当需要的时候可以从队列中取出未使用的连接。如果没有可用连接&#xff0c;则可以在一定时间内等待&#xff0c;直到队列中有可用的连接&#xff0c;否则将抛出…

浅谈估值模型:PB指标与剩余收益估值

摘要及声明 1&#xff1a;本文简单介绍PB指标的推导以及剩余收益的估值方式&#xff1b; 2&#xff1a;本文主要为理念的讲解&#xff0c;模型也是笔者自建&#xff0c;文中假设与观点是基于笔者对模型及数据的一孔之见&#xff0c;若有不同见解欢迎随时留言交流&#xff1b…

【HTML】HTML 标签 ① ( 骨架标签 | 双标签和单标签 | 嵌套关系和并列关系 | 文档类型 | 页面语言 | 编码字符集 )

文章目录一、HTML 标签简介二、HTML 骨架标签三、双标签和单标签四、嵌套关系和并列关系五、文档类型六、页面语言七、编码字符集一、HTML 标签简介 HTML 英文全称 " HyperText Mark-up Language " , 中文名称是 " 超文本标记语言 " ; 多媒体 : 超文本 指…

小 C 爱观察(observe)

小 C 爱观察&#xff08;observe&#xff09;题目描述输入格式输出格式样例输入数据#1输出数据#1解释#1输入数据#2输出数据#2输入数据#3输出数据#3题目描述 小 C 非常喜欢树。上次后院的蚂蚁看腻了&#xff0c;这次准备来观察树。 小 C 每天起得早早的&#xff0c;给小树浇水…

shell 流程控制之条件判断及案例

目录 流程控制之条件判断 一&#xff0c;if条件语句的语法及案例 1&#xff0c;单分支结构 2&#xff0c;双分支结构 3&#xff0c;多分支结构 二&#xff0c;复合指令 三&#xff0c; exit退出程序 四&#xff0c; 多条件判断语句case 流程控制之条件判断 条件判断语句…

【SpringCloud】Sentinel 之隔离与降级

一、上集回顾上级文章地址&#xff1a;【SpringCloud】Sentinel 之流量控制_面向架构编程的博客-CSDN博客上一篇文章我们讲解了Sentinel 流量控制、流控效果、热点参数限流的用法&#xff0c;统称为限流&#xff0c;它是一种预防措施&#xff0c;可以尽量避免因高并发而引起的服…

根据官方文档详细说明 Kubernetes 网络流量走向,包含详细的图文说明和介绍

根据官方文档详细说明 Kubernetes 网络流量走向&#xff0c;包含详细的图文说明和介绍。 阅读本文&#xff0c;你可以了解在 Kubernetes 内外&#xff0c;数据包是如何转发的&#xff0c;从原始的 Web 请求开始&#xff0c;到托管应用程序的容器。 Kubernetes 网络要求 在深入…

【three.js】本地搭建Threejs官方文档网站 解决threejs官方文档打开过慢得到问题

本文主要为了解决three.js 官方文档 打开过慢的问题 因为Three.js官网是国外的服务器&#xff0c;所以为了方便学习和快速的查阅文档&#xff0c;我们可以自己搭建Three.js官网和文档&#xff0c;方便随时查看案例和文档内容进行学习。 1、首先进入threejs库GitHub地址&#xf…

如何成为一名FPGA工程师?需要掌握哪些知识?

我国每年对于FPGA设计人才的需求缺口很大。在需求缺口巨大的情形下&#xff0c;发展前景相对可观。那么如何成为一名FPGA工程师&#xff1f; 什么是FPGA&#xff1f; FPGA&#xff08;FieldProgrammable Gate Array&#xff09;&#xff0c;即现场可编程门阵列&#xff0c;它…

新手入门Pinia

什么是Pinia Pinia 是 Vue 的专属状态管理库&#xff0c;它允许你跨组件或页面共享状态。它和Vuex作用类似(发音为 /piːnjʌ/),官网 为什么要使用Pinia 与 Vuex 相比&#xff0c;Pinia 不仅提供了一个更简单的 API&#xff0c;也提供了符合组合式 API 风格的 API&#xff0…

vue项目创建

前提&#xff1a;node安装&#xff1a;02node安装_哔哩哔哩_bilibili 1. 查看node版本 查看node版本 node -v 查看npm 版本 npm -v 2. 输入cmd 用管理员打开控制台 3. 设置淘宝镜像 npm config set registry https://registry.npm.taobao.org 4. 安装vue脚手架 npm install -g …

北大青鸟昌平校区:2023年云计算发展趋势!

云计算的大规模应用一直是许多最具变革性技术——如人工智能、物联网等的关键驱动力&#xff0c;未来也将进一步推动虚拟现实和增强现实(VR/AR)、元宇宙、甚至量子计算等技术的发展。近日&#xff0c;在美国《福布斯》网站报道中&#xff0c;列出了2023年云计算领域的五大主要趋…

56.Isaac教程--ROS

ROS ISAAC教程合集地址文章目录ROS安装ROS创建和使用自定义 ROS 包创建 ROS BridgeRos节点时间同步器消息转换器基地姿势同步自定义小码示例&#xff1a;将 ROS 导航堆栈与 Isaac 结合使用在此示例上构建将 Isaac 映射转换为 ROS 映射Isaac 和机器人操作系统 (ROS) 都使用消息传…