C++ ---- 入门基础知识总结

news2024/9/25 15:21:23

思维导图

目录

命名空间

命名冲突

如何定义命名空间

命名空间定义语法

嵌套定义

同一工程下定义同名命名空间

命名空间的使用

命名空间名称和作用域限定符(: :)

using将命名空间中某个成员“释放”出来

using namespace 命名空间名称

C++标准库命名空间std

C++输入/输出

Hello World的四种写法

自动识别类型

缺省参数

全缺省

半缺省(部分缺省)

缺省值同时出现在声明和定义中

函数重载

构成函数重载的三种场景

参数类型不同

参数个数不同

参数类型顺序不同

缺省和函数重载二义性问题

C++函数修饰规则(linux下测试)

返回值不同不构成函数重载

引用

引用概念

语法特性

应用场景

引用做参数

引用做返回值

常引用

权限的平移(可以)

权限的缩小(可以)

权限的放大(不可以)

 临时变量具有常性

引用和指针的对比

内联函数

概念

内联函数的特性

和宏对比


命名空间

在C/C++中,经常要自定义一些变量、函数在全局或者局部,这些变量名和函数名可能会存在冲突的问题。在C++中提出了命名空间的概念,其作用就是对标识符的名称(变量名、函数名等命名)进行本地化,避免和库中的命名或者其他命名空间中的命名冲突。

命名冲突

下述示例代码中定义了一个malloc全局变量,但是这个命名在库中是个函数的名称,出现了命名冲突问题:

#include <stdio.h>
#include <stdlib.h>

//变量名和库中定义冲突
int malloc = 100;
int main()
{
	printf("%d\n",malloc);	
	return 0;
}

 上述命名冲突的问题在C++中可以通过定义命名空间的方式来解决!

namespace zxy
{
	int malloc = 100;
}
int main()
{
	printf("%d",zxy::malloc);	
	return 0;
}

如何定义命名空间

命名空间定义语法

namespace关键字+命名空间的名称+{}就定义好了一个命名空间:

语法:namespace 命名空间名称 {}

下面的代码中定义了两个命名空间zxy1和zxy2, 两个空间中分别定义了a、b两个变量和add函数,但是它们在不同的域中,不存在冲突问题。

namespace zxy1
{
    int a = 985;
    int b = 211;

    int add(int a, int b)
    {
        return a + b;
    }
}
namespace zxy2
{
    int a = 100;
    int b = 200;
    int add(int a, int b)
    {
        return (a + b) * 10;
    }
}

嵌套定义

在命名空间zxy1中嵌套了一个命名空间zxy2:

namespace zxy1
{
	int a = 10;
	namespace zxy2
	{
		int b = 10;
	}
}

同一工程下定义同名命名空间

需要注意的是,当在同一工程下定义了同名的命名空间后,不管定义了多少,编译器最后会把它们合成一个命名空间,虽然你定义了多次,但都是在一个作用域中。这时就要注意命名冲突的问题了。

test1.h

namespace zxy
{
	int a = 10;
	int b = 20;
}

test2.h

namespace zxy
{
	int c = 13;
	int d = 14;
}

在编译器的视角下,它们是这样的:

namespace zxy
{
	int a = 10;
	int b = 20;
	int c = 13;
	int d = 14;
}

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

2.同一工程下同名命名空间最终会被合并成一个。

3.嵌套定义的命名空间,如果想要访问内部的命名空间要先找到其外部的命名空间。

4.关键字namespace 定义命名空间。

命名空间的使用

命名空间名称和作用域限定符(: :

namespace zxy
{
	int a = 10;
	int b = 20;
	int c = 30;

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

int main()
{
	printf("%d\n",zxy::a);
	printf("%d\n", zxy::add(zxy::b, zxy::c));
	return 0;
}

using将命名空间中某个成员“释放”出来

将某个成员从指定命名空间中引入:

namespace zxy
{
	int a = 10;
	int b = 20;
}

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

using namespace 命名空间名称

该命名空间中的全部成员被引入:

namespace zxy
{
	int a = 10;
	int b = 20;
	int c = 30;

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

using namespace zxy;
int main()
{
	printf("%d\n",a);
	printf("%d\n",add(c,b));
	return 0;
}

1.(: :)作用域限定符。

2.using + 命名空间名称 + 作用域限定符 + 命名空间中某个成员(using N: :a),将命名空间中的某个成员引入。

3.using+namespace+命名空间名(using namespace N),将整个命名空间中的内容引入。

4.命名空间名称+作用域限定符+某个成员(N : : x)。

C++标准库命名空间std

初始C++的过程中,常见的一行代码:

using namespace std;

基于上述命名空间的知识,这行代码的作用是将C++标准库命名空间的内容展开,这样做的目的是在日常练习中更加的便捷的使用std空间中的内容。缺点是文章开头提到的命名冲突问题。

C++输入/输出

1.cout是ostream类型的对象,cin是istream类型的对象,endl表示换行,它们都包含在<iostream>头文件中。

2.<<是流插入运算符,>>是流提取运算符。 

3.C++标准库的定义实现都放到了std命名空间中。

Hello World的四种写法

有了上述的描述,现在动手写一个“Hello World”:

#include <iostream>
#include <stdio.h>
//方法2:全部引入
using namespace std;
//方法3:部分引入
using std::cout;
using std::cin;
int main()
{
	//方法1:不引入
	std::cout << "Hello World!" << std::endl;
	//方法2和3写法一样:
	cout << "Hello World!" << endl;
	//方法4:printf(C++兼容C)
	printf("Hello Word!\n");
	return 0;
}

上述代码展示了命名空间的几种不同用法,也使用了cout标准输出对象。但是有些场景下printf也有它的一些优势,根据实际情况选择不同的实现方法。 

自动识别类型

#include <iostream>
using namespace std;

int main()
{
	int a;
	double b;
	char ch;
	cin >> a >> b >> ch;

	cout << "int:" << a << endl;
	cout << "double:" << b << endl;
	cout<<"char:" << ch << endl;

	return 0;
}

 自动识别类型的原理

ostream和istream类中分别对<<流插入和>>流提取运算符进行了重载:

缺省参数

全缺省

#include <iostream>
using namespace std;

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

int main()
{
	Fun();//不传参,用缺省值
	Fun(100, 200);//传参
	return 0;
}

半缺省(部分缺省)

半缺省给缺省值的时候必须从右往左依次给,不能出现间隔。

错误示例:

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

正确使用

#include <iostream>
using namespace std;

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

int main()
{
	Fun(10);
	Fun(100, 200);
	Fun(100, 200,300);
	return 0;
}

在传参的时候是按照顺序穿的,不可以间隔这传参!如:Fun(100, , 200);这是错误的写法。

缺省值同时出现在声明和定义中

在声明和定义中同时出现缺省值是不可以的,如果两个位置给的缺省值不同,编译器就无法确定该用哪个缺省值,所以不支持这样的语法。解决方法就是只在声明中给缺省值

#include <iostream>
using namespace std;

void Fun(int a = 30, int b = 10, int c = 20);

int main()
{
	Fun(10);
	Fun(100, 200);
	Fun(100, 200,300);
	return 0;
}

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

1.部分缺省的缺省值要从右向左给,不能间隔给缺省值。

2.部分缺省传参的顺序是从左向右传参,不能间隔传参。

3.缺省值不能在声明和定义中同时出现,只在声明中给。

函数重载

C++中允许在同一作用域中出现同名函数,这些同名函数的形参列表必须不同(参数个数不同,参数类型不同,参数顺序不同)。

构成函数重载的三种场景

参数类型不同

//类型不同是不同
int add(int a, int b)
{
	cout << "int:" ;
	return a + b;
}

double add(double c, double d)
{
	cout << "double:" ;
	return c + d;
}

参数个数不同

//个数不同是不同
void fun(int a)
{
	cout << "一个参数"<< endl;
}
void fun(int c, int d)
{
	cout << "两个参数" <<endl;
}

参数类型顺序不同

//参数类型顺序不同
void fun2(int a, char b)
{
	cout << "int ,char" << endl;
}
void fun2(char c, int d)
{
	cout << "char int" << endl;
}

缺省和函数重载二义性问题

下述代码中,无参的fun和两个参数的fun构成了函数重载,但是有参的fun参数给了缺省值,调用的时候以可以fun();调用,当在main函数中调用fun()时,就出现了函数调用不明确的错误。

int fun()
{
	cout << "fun()" << endl;
}
int fun(int a = 10,int b = 20)
{
	cout << "fun(int,int)" << endl;
}
int main()
{
	//二义性,调用不明确
	fun();
	return 0;
}

C++函数修饰规则(linux下测试)

C++支持函数重载是因为C++通过函数修饰规则将同名函数进行了修饰,对于上述参数不同的情况修饰出来的名字不同!

●原理分析

一个程序要运行,需要经历预处理、编译、汇编、链接几个阶段!在链接阶段,当链接器看到有函数调用时,但没有该函数的地址,会去寻找该函数的地址,然后链接到一起。C语言中同名函数没法区分,所以不支持重载。C++对函数名进行了修饰(编译器不同修饰规则可能不同),在链接器的视角来看就是不同的函数名称,所以C++支持函数重载。

●Linux下g++测试

#include <iostream>
using namespace std;

int fun(int a,int b)
{
    return a+b;
}

int fun(int c,double d)
{
    return c;
}

int main()
{
    fun(10,20);
    fun(15,23.4);
    return 0;
}
objdump -S xxxxxx

返回值不同不构成函数重载

按照上述函数名修饰规则支持函数重载的原理,将返回值类型也进行修饰,就可以对同名函数进行区分。但是语法上不支持这样做,原因是在函数调用阶段,没办法指明返回值,函数调用存在二义性。所以返回值不同,不能构成函数重载

int add(int a, int b)
{
	return 10;
}
double add(int c, int d)
{
	return 13.14;
}

int main()
{
	//函数调用阶段无法指明返回值
	add(1,2);
	add(3, 4);
}

1.构成函数重载的三种条件,参数个数不同,参数类型不同,参数类型顺序不同。

2.全缺省和无参同名函数在调用时可能存在调用不明确的问题。

3.返回值不同不能构成函数重载,原因是在函数调用阶段无法指明返回值。

4.C++支持函数重载的原因,是根据函数名修饰规则对同名函数进行修饰,当满足函数重载条件(“三不同”)时,在链接器看来它们就是不同的函数名。

引用

C++中的引用和指针是相互辅佐的关系,有一部分功能是重叠的,各自又有其自身的特点。C++中的引用不能完全的替代指针。

引用概念

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

●ra引用变量a,在语法层面上没有给引用变量开辟空间。ra和a共用同一块内存空间。

int main()
{
	int a = 100;
	int& ra = a;

	cout <<"&a:" << &a << endl;
	cout <<"&ra:" << &ra << endl;
    return 0;
}

 

 取地址a和取地址ra得到的结果是相同的,说明两者共用同一块空间。

int main()
{
	int a = 100;
	int* ra = &a;

	cout <<"&a:" << &a << endl;
	cout <<"&ra:" << &ra << endl;//取到的是指针的地址
    return 0;
}

 取地址ra取的是指针变量的地址,如果想要取到a的地址,要先对指针变量解引用在取a的地址。

语法特性

引用在定义时必须初始化!

	int a = 10;
	int& ra = a;

	const int& rb = 20;

一个变量可以有多个引用。

	int a = 10;
	int& ra = a;

	int& rra = a;

	int& rrra = rra;

引用一旦引用一个实体,就不能在引用其他实体。

应用场景

引用做参数

传参局部解析(传值调用)

观察上述局部的汇编代码解析图,在add函数调用的过程中,首先先将实参拷贝到寄存中,在压入到函数栈帧。“形参是实参的一份临时拷贝”,通过上图可以更好的理解这句话。

●引用做参数(输出型参数)的优点是减少了一次拷贝,修改形参,实参也跟着修改。这部分功能和指针是重叠的。

void Swap(int& left, int& right)
{
	int tmp = left;
	left = right;
	right = tmp;
}
int main()
{
	int a = 10,b=20;
	cout << "交换前:a=" << a << ",b=" << b << endl;
	Swap(a,b);
	cout << "交换后:a=" << a << ",b=" << b << endl;
	return 0;
}

引用做返回值

●栈帧销毁,返回值返回过程

如上图所示,在函数返回值返回的过程中,并不是直接返回,而是生成临变量拷贝到寄存器上,如果数据较大也可能保存在上层栈帧中,在间接返回给ret。 

●出了作用域返回对象还在(传引用返回,减少拷贝)

int& Fun2()
{
	static int N = 10;
	N++;
	return N;
}
int main()
{
	int ret2 = Fun2();
	cout << ret2 << endl;
	
    return 0;
}

●出了作用域返回对象不在(传值返回)

int Fun1()
{
    int N = 10;
	N++;
	return N;
}
int main()
{
	int ret1 = Fun1();
	cout << ret1 << endl;

	return 0;
}

当函数返回时,出了函数作用域,如果要返回的对象还在,适用于传引用返回,优点是减少了一次拷贝。如果出了函数作用域对象销毁,则要使用传值返回。

●错误场景

出了函数作用域销毁的局部变量,采用传引用返回:

int& Fun3()
{
	int a = 100;

	return a;
}

int main()
{

	int ra = Fun3();
	return 0;
}

 需要注意的是,当函数调用结束,栈帧销毁后。并不是空间不存在了,而是失去了访问该空间的权利,该空间也不在被保护。

常引用

指针和引用的赋值中,存在权限的放大和缩小问题!!!

权限的平移(可以)

int main()
{
	int a = 10;
	const int b = 20;
	
	int& ra = a;//权限的平移
	const int& rb = b;//权限的平移

	return 0;
}

权限的缩小(可以)

int main()
{
	int a = 10;
	const int& rra = a;//权限的缩小

	return 0;
}

权限的放大(不可以)

int main()
{
	const int b = 20;
	int& rrb = b;
	
	return 0;
}

 临时变量具有常性

如上述的场景中,在类型转换或者传值返回的过程中,会产生临时变量,它们是具有常性的,对它们引用,要用常引用。 

场景1:

int main()
{
	int a = 10;
	double b = 13;

	const int& rb = b;

	return 0;
}

 场景2:

int Fun()
{
	int n = 10;
	return n;
}

int main()
{
	const int& rn = Fun();
	return 0;
}

引用和指针的对比

1.引用在底层上实际上是有空间的,引用是按照指针方式实现的。在语法层认为,引用是一个别名,没有独立空间,和引用实体共用同一块空间。

2.引用和指针是互补的,各有优点。

3.引用在概念上是一个变量的别名不需要额外的空间(语法层面上),指针要存储一个变量的地址。

4.引用在定义时必须初始化,指针没有要求。

5.引用很专一,引用了一个实体后就不能在引用其它实体。指针的指向随意改变。这也是引用无法代替实体的原因只一,不能改变指向,诸如链表的增删查改就无法得到很好的实现。

6.没有空引用,但有空指针。

7.在sizeof中的含义不同,sizeof(引用)计算的是引用实体的类型大小,指针不管指向的是什么类型的数据,计算的都是地址空间所占字节的大小,32位平台占4字节,64位平台下占8字节。

8.引用++和--是引用的实体改变,指针++和--是向后或者向前偏移一个类型的大小。

9.有多级指针,没有多级引用,引用一个别名,实际上和引用实体是一样的。

10.访问实体的方式不同,指针需要解引用,引用编译器自己处理,用户直接使用即可。

11.引用比指针更加的安全。

内联函数

概念

关键字inline修饰的函数叫做内联函数,编译器会在编译的预处理阶段将内联函数展开,没有函数调用建立栈帧的消耗,内联函数提升程序运行的效率。

●正常函数调用

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

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

	cout << ret << endl;
	return 0;
}

 上述汇编代码是正常函数调用,call add跳转到目标函数。

●内联函数调用

在debug模式下,编译器默认不会展开inline函数,需要对编译器进行设置。

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

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

	cout << ret << endl;
	return 0;
}

 通过对汇编代码的观察可以发现,内联函数确实被展开了。

内联函数的特性

1.inline是以空间换时间的做法,如果将编译器将函数当成内联函数处理,在编译阶段,会用函数体替换函数调用。缺点:最后形成的目标文件会变大。优点:少了函数调用创建栈帧的开销,提高程序的运行效率。

2.函数前加了inline关键字,只是对编译器的建议,编译器可以忽略。一些比较成的函数编译器不会将其展开。

inline int add(int a, int b)
{
	int c = a + b;
	c = a + b;
	c = a + b;
	c = a + b;
	c = a + b;
	c = a + b;
	c = a + b;
	c = a + b;
	c = a + b;
	c = a + b;
	c = a + b;
	c = a + b;
	c = a + b;
	c = a + b;
	c = a + b;
	c = a + b;
	c = a + b;
	c = a + b;
	return c;
}

int main()
{
	int a = 10, b = 20;
	int sum = 0;
	sum = add(a,b);
	return 0;
}

 如上述测试函数,进行了inline声明。但是最终是否展开取决于编译器,较长的函数,编译器会忽略内联的请求。

3.内联适用于代码规模小,频繁调用的函数。

4.内联函数的声明和定义分离会导致报错,原因是内联函数函数名不进入符号表,在链接的过程中,找不到函数地址。

add.cpp

inline int add(int a, int b)
{
	int c = a + b;
	return c;
}

add.h

#pragma once
int add(int a, int b);

test.cpp

#include <iostream>

using namespace std;
#include "add.h"

int main()
{
	int a = 10, b = 20;
	int sum = 0;
	sum = add(a,b);
	
	cout << sum << endl;

	return 0;
}

 

链接错误: 

和宏对比

●替代宏的技术

1.常量的定义:const或者枚举enum

2.短小函数的定义,用内联函数

●宏和内联函数对比

1.代码长度

宏在预处理阶段进行替换,内联函数在编译阶段展开。都会使程序的长度变长。

2.执行速度

宏和内联函数都没有函数栈帧创建和销毁的消耗,执行速度比函数调用快。

3.参数类型

宏的参数与类型无关,不进行类型检测,所以宏的使用不够严谨。内联函数的使用和常规函数相同,参数与类型是有关的。

4.调试

宏不支持调试,内联函数支持调试。

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

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

相关文章

Go:值与指针

1. 计算机中的值 在百万年的演化历史中&#xff0c;人类对事物的属性进行了抽象&#xff0c;有了数量、精度、信息等概念的表示&#xff0c;对应的我们称之为整数、小数、文本文字等。计算机出现后&#xff0c;我们使用计算机对真实世界的问题进行建模&#xff0c;通过计算机的…

WIN10安装CUDA保姆级教程[2023.5.7更新]

本系列分步记录在win10上搭建CUDAcudnnpytorchYOLOv5tensorrt等深度学习架构部署及系统搭建&#xff0c;欢迎关注追更&#xff01; 目录 0.了解CUDA 1.注意事项 1.1显卡驱动 1.2确定关联性 1.2.1 显卡驱动与cuda的对应关系&#xff1a; 1.2.2 pytorch与cuda的对应关系 2.c…

NLP大模型微调原理

1. 背景 LLM (Large Language Model) 大型语言模型&#xff0c;旨在理解和生成人类语言&#xff0c;需要在大量的文本数据上进行训练。一般基于Transformer结构&#xff0c;拥有Billion以上级别的参数量。比如GPT-3(175B)&#xff0c;PaLM(560B)。 NLP界发生三件大事&#xff…

ChatGLM-6B模型微调实战(以 ADGEN (广告生成) 数据集为例,序列长度达 2048)

kingglory/ChatGLM-6B 项目地址 1 介绍 对于 ChatGLM-6B 模型基于 P-Tuning v2 的微调。P-Tuning v2 将需要微调的参数量减少到原来的 0.1%&#xff0c;再通过模型量化、Gradient Checkpoint 等方法&#xff0c;差不多需要 7GB或则8GB 显存即可运行。 2 环境 2.1 python …

【软考-中级】系统集成项目管理工程师-计算题

系统集成项目管理工程师 二、计算题题型一&#xff1a;EMV&#xff08;预期货币价值&#xff09;题型二&#xff1a;加权系统题型三&#xff1a;自制和外贸决策——采购管理题型四&#xff1a;沟通渠道——沟通管理题型五&#xff1a;投资回收期、回收率题型六&#xff1a;进度…

metinfo_6.0.0 任意文件读取漏洞复现

一.漏洞简介 MetInfo是一套使用PHP和Mysql开发的内容管理系统。 MetInfo 6.0.0~6.1.0版本中的 old_thumb.class.php文件存在任意文件读取漏洞。攻击者可利用漏洞读取网站上的敏感文件。 二.漏洞影响 MetInfo 6.0.0 MetInfo 6.1.0 三.漏洞分析 在\MetInfo6.0.0\app\system\i…

推开“任意门”,华为全屋智能正在实现一代科幻迷的童年梦想

科幻作家亚瑟查理斯克拉克有句名言&#xff0c;“任何足够先进的科技&#xff0c;都和魔法无异”。 提到空间魔法&#xff0c;很多科技爱好者或科幻迷会想到哆啦A梦的“任意门”。通过那扇门&#xff0c;可以进入全新的世界&#xff0c;去任何想去的地方&#xff0c;是不少人在…

最新研究,GPT-4暴露了缺点!无法完全理解语言歧义!

夕小瑶科技说 原创作者 |智商掉了一地、Python自然语言推理&#xff08;Natural Language Inference&#xff0c;NLI&#xff09;是自然语言处理中一项重要任务&#xff0c;其目标是根据给定的前提和假设&#xff0c;来判断假设是否可以从前提中推断出来。然而&#xff0c;由于…

远程连接阿里云mysql数据库教程(SSH方式和宝塔面板方式)

一、SSH方式 1.首先登录mysql数据库 mysql -u root -p 输入密码后&#xff1a; 第一次连接的话该密码可以通过宝塔面板来重置&#xff1a; &#xff08;1&#xff09;输入 bt&#xff1a; &#xff08;2&#xff09;输入 7 即可重置mysql密码 2.查询mysql数据库中的user表 …

如何快速给pdf添加水印?

如何快速给pdf添加水印&#xff1f;在当今数字化时代&#xff0c;任何工作都是在电脑上完成了&#xff0c;PDF文档已成为人们日常工作中必不可少的一部分。虽然pdf文件具有较强的稳定性&#xff0c;不能被别人轻易的编辑修改&#xff0c;有时我们还需要提高pdf文件的安全性&…

AlphaFold的极限:高中生揭示人工智能在生物信息学挑战中的缺陷

人工智能程序AlphaFold (AlphaFold2开源了&#xff0c;不是土豪也不会编程的你怎么蹭一波&#xff1f;)&#xff0c;通过预测蛋白质结构解决了结构生物信息学的核心问题。部分AlphaFold迷们声称“该程序已经掌握了终极蛋白质物理学&#xff0c;其工作能力已超越了最初的设计”。…

Doc2Bot: 达摩院推出多类型文档对话数据集

一、概述 title&#xff1a;Doc2Bot: Accessing Heterogeneous Documents via Conversational Bots 论文地址&#xff1a;Doc2Bot: Accessing Heterogeneous Documents via Conversational Bots - ACL Anthology 数据地址&#xff08;大概5千多轮开源数据&#xff09;&#…

用 Spark 预测回头客

访问【WRITE-BUG数字空间】_[内附完整源码和文档] 至此“淘宝双 11 数据分析与预测课程案例”所需要的环境配置完成。另外实际操作中发现在案例教程中存在一些小问题&#xff0c;比如教程中 Eclipse 版本为 3.8&#xff0c;但是在配置 Tomcat Server 时又要求配置 v8.0 版本&a…

【分布式技术专题】「授权认证体系」OAuth2.0协议的入门到精通系列之授权码模式

这里写目录标题 OAuth2.0是什么OAuth2.0协议体系的Roles角色OAuth定义了四个角色资源所有者资源服务器客户端授权服务器 传统的客户机-服务器身份验证模型的问题 协议流程认证授权授权码 OAuth2.0是什么 OAuth 2.0是用于授权的行业标准协议。OAuth 2.0专注于简化客户端开发人员…

从【连接受限】看Android网络

从连接受限看Android网络 现象摸索从通知开始是Handler发的通知看看NetworkStateTrackerHandler NetworkMonitor做了什么NetworkMonitor是一个状态机CaptivePortalProbeResult从何而来连接受限的直接原因 嗅探是怎样进行的ProbeThread 回过头看看InternalHanderregisterNetwork…

GRE 隧道协议

1.GRE协议简介 GRE&#xff08;General Routing Encapsulation &#xff0c;通用路由封装&#xff09;是对某些网络层协议(如IP和IPX)的数据报文进行封装&#xff0c;使这些被封装的报文能够在另一网络层协议(如IP)中传输。此外 GRE协议也可以作为VPN的第三层隧道协议连接两个…

ES6之迭代器

文章目录 前言迭代器1.原生具备Iterator接口的数据&#xff08;可用for...of遍历&#xff09;2.工作原理3.自定义遍历数据 总结 前言 迭代器&#xff08;Iterator&#xff09; for…of遍历 迭代器 迭代器是一种接口&#xff0c;为各种不同数据结构提供统一的访问机制。任何数…

c++ 11标准模板(STL) std::vector (八)

定义于头文件 <vector> template< class T, class Allocator std::allocator<T> > class vector;(1)namespace pmr { template <class T> using vector std::vector<T, std::pmr::polymorphic_allocator<T>>; }(2)(C17…

智慧工地烟火识别算法 opencv

智慧工地烟火识别系统应用pythonopencv深度学习算法模型技术分析前端视频信息&#xff0c;智慧工地烟火识别算法模型主动发现工地或者厂区现场区域内的烟雾和火灾苗头及时进行告警。OpenCV的全称是Open Source Computer Vision Library&#xff0c;是一个跨平台的计算机视觉处理…

前端三剑客 - HTML

前言 前面都是一些基础的铺垫&#xff0c;现在就正式进入到web开发环节了。 我们的目标就是通过学习 JavaEE初阶&#xff0c;搭建出一个网站出来。 一个网站分成两个部分&#xff1a; 前端&#xff08;客户端&#xff09; 后端&#xff08;服务器&#xff09; 通常这里的客户端…