《深入探究:C++ 在多方面对 C 语言实现的优化》
目录
- 一、C++ 在 C 上进行的优化
- 二、C++ 关键字(C++ 98)
- 三、C++ 的输入输出
- 1. cin 和 cout 的使用
- 2. cin、cout 和 scanf()、printf() 的区别
- 三、命名空间
- 1. 命名空间的使用
- 2. 嵌套命名空间
- 3. 在多个头文件中使用相同的命名空间
- 四、函数缺省值
- 1. 缺省值的使用
- 2. 缺省值使用的注意事项
- 五、函数重载
- 1. 函数重载的使用
- 2. 为什么函数返回类型不同不算函数重载?
- 六、引用
- 1. 引用的使用
- 2. 常量引用
- 3. 常量引用和普通引用的区别
- 5. 引用传参
- 6. 引用的注意事项
- 七、内联函数
- 1. 内联函数的使用
- 2. 内联函数的注意事项
- 3. 宏的优缺点?C++ 有哪些技术替代宏?
- 八、auto 关键字
- 1. auto 关键字的使用
- 2. auto 关键字使用的注意事项
- 九、基于范围的 for 循环
- 1. 范围 for 的使用
- 2. 范围 for 的使用条件
- 十、空指针 nullptr(C++11)
一、C++ 在 C 上进行的优化
C++ 在 C 的基础上加入了面向对象编程、泛型编程和许多有用的库。弥补了 C 语言的不足,并对 C 语言不合理的地方进行优化,使其更加适应当前时代的需求和发展。
由于 C++ 兼容大部分的 C,所以可以在 C++ 中混合使用 C 来进行编写代码,如使用 printf() 函数和 scanf() 函数。
二、C++ 关键字(C++ 98)
下面的关键字看看就行,不用背,用的多了就记住了,很多都是 C 语言学过的。
三、C++ 的输入输出
在 C++ 中,输入输出被看成输入流和输出流,使用 iostream 库中的 istream 和 ostream 分别表示输入流和输出流。标准输入就可以理解为把键盘敲击输入的信息放入输入流中,而标准输出就可以理解为把输出的信息放入输出流中,随着输出流显示到显示器上。一个流就是一个字符。术语 “流” 的意思是,随着时间的推移,字符是顺序生成或者消耗的。
而标准库定义了名为 cin 的 istream 类的对象和名为 cout 的 ostream 类的对象并通过流插入运算符(<<)和流提取运算符(>>)用来处理标准输入和标准输出。cin 和 cout 均可智能识别其后数据的类型。
1. cin 和 cout 的使用
首先,使用 cin 和 cout 输入输出对象需要完成下面两步:
1)包含 iostream 库,因为 istream 类和 ostream 类包含在 iostream 库中。
2) 使用标准命名空间 std,或者单独声明 cin 和 cout。
// 头文件
#include <iostream>// 使用标准命名空间 std
using namespace std;int main()
{int i = 0;double d = 0;char c = 0;// 输入cin >> i; // 单个变量输入cin >> d >> c; // 多个变量连续输入// 输入cout << "i = " << i << endl;cout << "d = " << d << endl;cout << "c = " << c << endl;return 0;
}
在上述代码中,流提取运算符(>>)搭配 cin 使用,流插入运算符(<<)搭配 cout 使用,后面跟需要输入和输出的数据即可。也可以连续输入和输出,因为 cin 和 cout 在输入和输出完成第一个数据之后会返回一个类对象的引用。连续输入只要中间间隔空白(空格、制表符和换行符)即可。
endl 是 C++ 的操纵符,把它写入标准输出流的作用是换行并刷新缓冲区。
代码运行结果如下:
2. cin、cout 和 scanf()、printf() 的区别
1)cin、cout 是类对象,而 scanf() 和 printf() 是函数;
2)cin、cout 使用流插提取运算符(>>)和流插入运算符(<<)来进行输入和输出,scanf() 和 printf() 使用参数传递的方式来进行输入和输出;
3)cin、cout 适用于非格式化输入和输出,scanf() 和 printf() 适合格式化输入和输出。
三、命名空间
当我们包含库中的头文件时,由于该头文件中的内容过多,很容易和我们自己命名的名称冲突。当我们和他人一起编写大型项目时,我们和他人命名的名称也很容易冲突。
上面的问题放在 C 语言中,只能使用不同的名称,而在 C++ 中可以通过使用关键字 namespace 创建命名空间来解决。
1. 命名空间的使用
创建命名空间的格式为:namespace 名称 { … }
// 头文件
#include <iostream>// 使用标准名称空间
using namespace std;// 创建命名空间 qcx
namespace qcx
{int a = 3;// 交换函数void Swap(int* a, int* b){int tmp = *a;*a = *b;*b = tmp;}
}// 交换函数
void Swap(int* a, int* b)
{int tmp = *a;*a = *b;*b = tmp;
}int a = 2;int main()
{int a = 1;cout << "局部变量: " << a << endl;cout << "全局变量: " << ::a << endl;cout << "命名空间: " << qcx::a << endl;return 0;
}
上述代码运行结果如下:
可以看到,代码正常运行。且在上述代码中,出现了三个同名变量 a,和两个一模一样的函数,倘若这放在 C 语言中,编译阶段就已经报错了。
第一条 cout 语句中的变量 a 是局部变量,当全局变量名和局部变量名冲突时,局部优先,且编译器在使用变量名时,会先在局部查找,然后在全局查找,不会主动访问命名空间的内容。第二条 cout 语句中的变量 a,使用 C++ 中的作用域解析运算符(::),当该运算符的左侧为空白时,默认访问全局变量。第三条 cout 语句,使用作用域解析运算符(::)显示访问命名空间 qcx 中的变量 a。
名称冲突是在同一个作用域中出现了同名的变量或者函数,而命名空间的作用是开辟一个新的作用域,所以上述代码中的三个 a 变量的作用域分别为:局部作用域,全局作用域,命名空间作用域,所以不会造成命名冲突。
(1)为什么包含头文件 iostream 后还需要使用标准命名空间 std ?
在学习 C 语言的时候,包含的头文件在编译阶段就直接展开了,且该头文件包含的内容可以直接使用。
但是,C++ 把标准库中的内容全部封装到了标准命名空间 std 中,比如现在包含头文件 iostream 相当于包含了如下内容:
namespace std
{
iostream 文件的内容
}
就像我们前面说的,编译器是不会主动访问命名空间中的内容的,所以如果仅仅只包含该头文件,我们是不能去使用里面的工具的。
而语句 using namespace std; 的作用是把外面的 namespace std 去掉,把里面的内容显示出来,也就相当于学习 C 语言时的包含头文件。
但是,如果直接使用 using namespace std,不就相当于命名空间白用了?把头文件中的内容全部展开和 C 语言不就没有区别了?所以,C++ 还提供了把命名空间里面的单个工具展开,如:using std::cout;,把 cout 类对象放入全局,这样我们就可以使用 cout 工具,且不用担心名称冲突了。
当然如果不嫌麻烦,也可以显示访问命名空间 std,如:std::cout << qcx::a << std::endl;。
(2)命名空间中可以存放变量、结构体、函数、类等内容
2. 嵌套命名空间
嵌套命名空间就是一个命名空间里面再包含命名空间,和嵌套循环一个意思。这个很容易理解,比如我们制作一款游戏,那么把战斗模块和数值模块分的代码放入各自的命名空间,然后战斗模块的每个组的代码放入各自的命名空间,最后每个组的成员的代码又放入各自的命名空间。
具体效果类似如下代码:
// 游戏
namespace game
{// 战斗模块namespace Battle{// a 组namespace a{// 小王namespace wang{// 代码...}// 小张namespace zhang{// 代码...}}// b 组namespace b{// 小王namespace wang{// 代码...}// 小张namespace zhang{// 代码...}}}// 数值模块namespace Numerical{// a 组namespace a{// 小王namespace wang{// 代码...}// 小张namespace zhang{// 代码...}}// b 组namespace b{// 小王namespace wang{// 代码...}// 小张namespace zhang{// 代码...}}}
}
如果需要访问战斗模块 a 组小王的变量 age,可以使用如下方法:
1)using Game::Battle:: a::wang::age;
2)using namespace Game::Battle:: a::wang;
(上面 a 前面加个空格是CSDN防止格式化)
3. 在多个头文件中使用相同的命名空间
比如在头文件 head1 中创建命名空间 qcx,然后在头文件 head2 中创建命名空间 qcx,那么这两个命名空间会合并为一个命名空间。如果在这两个头文件的 qcx 命名空间中定义了相同的名称,编译器会报错。
四、函数缺省值
函数缺省值的作用是不给函数传递参数时,函数使用默认值。在创建顺序表时,通常我们需要传递一个参数来初始化顺序表的大小,但是有时又不确定这个值给多大,给大了浪费空间,给小了需要扩容。所以可以给一个缺省值。
1. 缺省值的使用
// 头文件
#include <iostream>
#include <stdlib.h>// 使用声明
using std::cout;
using std::endl;// 类型声明
typedef int DataType;// 顺序表
struct SQList
{DataType* pdata;size_t size;size_t capacity;
};// 初始化顺序
void InitSQList(SQList* sl, int capacity = 2)
{// 申请空间sl->pdata = (DataType*)malloc(sizeof(DataType) * capacity);if (nullptr == sl->pdata){perror("InitSQList::malloc: ");return;}// 初始化成员sl->size = 0;sl->capacity = capacity;
}// 获得顺序表的容量
size_t GetCapacity(SQList* sl)
{return sl->capacity;
}int main()
{// 创建顺序表SQList s1, s2;// 使用缺省参数InitSQList(&s1);// 传递参数InitSQList(&s2, 8);// 打印容量cout << "s1 的容量:" << GetCapacity(&s1) << endl;cout << "s2 的容量:" << GetCapacity(&s2) << endl;return 0;
}
可以看到程序的运行结果如下:
2. 缺省值使用的注意事项
(1)函数声明填写缺省值,函数定义不写
这样做的好处是防止两边对不上,其次编译阶段需要检查函数声明,如果函数声明不写,函数定义写的话,编译阶段就会报错。
(2)函数缺省值需要从右往左依次填写
由于函数传参是从左到右依次传递的,所以函数缺省值需要从右往左依次缺省。因为C++在传递参数的时候不允许有参数为空。
(3)所有参数都有缺省值叫全缺省,部分参数有缺省值叫班缺省
五、函数重载
函数重载顾名思义就是在相同的作用域中可以存在两个相同名称的函数。这放在 C 中是不允许的,因为 C 中识别函数主要是通过函数名来识别的,而C++中加上了参数。
举个简单的例子,就拿函数 void Swap(int a, int b) 来说,在 C 语言中可能就是通过 Swap 来识别,但是在 C++ 中,是通过 Swapii,来识别,后面的 ii 代表了两个 int 参数。
所以,C++ 支持函数重载,只要函数的参数数量、类型和顺序不同即可。(上述只是简单说明,编译器具体的识别肯定不想上述这么简单)
1. 函数重载的使用
// 头文件
#include <iostream>// 使用声明
using std::cout;
using std::endl;// 交换函数
void Swap(int* a, int* b)
{int tmp = *a;*a = *b;*b = tmp;
}void Swap(double* a, double* b)
{double tmp = *a;*a = *b;*b = tmp;
}int main()
{int a = 1, b = 2;Swap(&a, &b);cout << "a = " << a << endl;cout << "b = " << b << endl;double c = 1.1, d = 2.2;Swap(&c, &d);cout << "c = " << c << endl;cout << "d = " << d << endl;return 0;
}
程序运行结果如下:
&esmp; 可以看到通过使用函数重载,可以把一个函数的功能作用到不同类型的变量上。
2. 为什么函数返回类型不同不算函数重载?
如果两个函数仅仅只是函数返回值不同,那么在编译截断就会报错,由于函数调用语句一模一样,编译器不知道你想调用哪个函数。
六、引用
引用的作用是给已经存在的变量取一个别名,也就是引用变量和被引用的变量共用一块空间。
创建引用变量的格式为:类型 &引用变量名 = 被引用的变量名
1. 引用的使用
// 头文件
#include <iostream>// 使用声明
using std::cout;
using std::endl;int main()
{// 创建变量 aint a = 10;// b 是对 a 的引用,也就是 b 是 a 的别名int& b = a;// 值验证cout << "a = " << a << endl;cout << "b = " << b << endl;// 地址验证cout << "&a = " << &a << endl;cout << "&b = " << &b << endl;return 0;
}
程序的运行结果如下:
可以看到上述变量 a 和 变量 b 的值和地址均相同,可以得出它们都是代指同一块空间。就好像一个人拥有外号,如李逵又叫黑旋风,但是叫的都是同一个人。而引用所代表的就是这种关系。如下图所示:
2. 常量引用
常量引用相比于普通引用的区别就是其值不能修改,类似 const 变量和普通变量。
// 头文件
#include <iostream>// 使用声明
using std::cout;
using std::endl;int main()
{int a = 10;// 普通引用int& ra = a;ra = 1;cout << "a = " << a << endl;return 0;
}
普通引用可以修改:
常量引用不能修改:
从上述代码以及运行结果中可以看出,常量引用不能修改只能读取,普通引用既能修改又能读取。
3. 常量引用和普通引用的区别
1)常量引用既能引用常量又能引用变量,而普通引用只能引用变量。
2)常量引用不能修改,普通引用可以修改
5. 引用传参
引用传参非常好用,首先引用传参效率高,因为直接使用原对象,其次引用传参节省空间,因为引用和引用对象共用一块空间。
下面是使用引用传参的 Swap() 函数:
// 头文件
#include <iostream>// 使用声明
using std::cout;
using std::endl;// 交换函数
void Swap(int& a, int& b)
{int tmp = a;a = b;b = tmp;
}int main()
{int a = 10;int b = 20;// 交换前cout << "交换前:\n";cout << "a = " << a << endl;cout << "b = " << b << endl;// 交换后Swap(a, b);cout << "交换后:\n";cout << "a = " << a << endl;cout << "b = " << b << endl;return 0;
}
代码运行结果如下:
可以看到引用传参比指针传参还要香,不仅传参直接传递,在函数中也可以直接使用。而指针传参需要取地址,在函数中还需要解引用。
而且引用还可以作为返回值,其他类型作为返回值都需要先拷贝到一个临时对象,然后再返回,而引用作为返回值是直接返回,提升了效率。但是引用作为返回值不能返回局部变量。
6. 引用的注意事项
1)引用必须在初始化时绑定对应类型的对象,且绑定之后不能转换绑定对象;
2)引用不开辟空间,和被引用对象共用一块空间;
3)普通引用只能绑定变量,常量引用没有限制;
4)函数不能返回局部变量的引用;
5)传参时如果不需要修改值,传递常量引用,避免不小心修改;
6)不要把引用和指针混淆。
七、内联函数
函数调用需要建立栈帧,但是如果该函数仅仅只有寥寥几行代码,这样每次调用该函数的开销主要在建立栈帧上了。
C 语言通过宏来解决上述问题,如下代码:
// 头文件
#include <iostream>// 使用声明
using std::cout;
using std::endl;// 宏声明
#define Add(x, y) (((x) + (y)) * 10)int main()
{cout << Add(10, 20) << endl;return 0;
}
通过上述代码可以发现,虽然宏能解决这个问题。但是宏是在编译过程中直接替换的,也不进行类型检查,且写法复杂,又由于运算符优先级要在表达式的每个部分加上括号。
C++ 通过内联函数解决上述问题,直接在函数前面加上 inline 即可。内联函数的作用是,当运行到函数调用语句时,直接展开函数体,也就是用函数体替换函数调用语句。
1. 内联函数的使用
// 头文件
#include <iostream>
#include "head1.h"// 使用声明
using std::cout;
using std::endl; 宏声明
//#define Add(x, y) (((x) + (y)) * 10)int main()
{ 宏声明//cout << Add(10, 20) << endl;// 内联函数Add(10, 20); // 相当于 return (10 + 20) * 10;return 0;
}
内联函数相当于在函数调用语句处展开函数体(带入参数值)。
2. 内联函数的注意事项
1)online 关键字只能添加在函数声明;
2)添加 online 关键字只是建议编译器让该函数成为内联函数,具体还需要编译器自行判断;
3)一般把内联函数直接定义在头文件中,其他文件需要使用只需要包含该头文件即可;
4)长度过长的函数和递归函数不适合成为内联函数,
5)内联函数只在 release 下起作用,在 debug 下不起作用;
6)内联函数不建议声明和定义分离,因为 inline 展开了,就找不到函数地址了,链接错误。
3. 宏的优缺点?C++ 有哪些技术替代宏?
(1)
优点:
1)针对不带参宏,提升了代码的可读性和可维护性;
2)针对带参宏,减少了函数栈帧的开销,提升了效率。
缺点:
1)缺少类型检查;
2)针对带参宏,可读性差,可维护性差,容易用错(由于运算符的优先级,必须在表达式的每个部分加上括号)
(2)
1)C++ 使用关键字 const 来定义常量;
2)C++ 使用内联函数替换带参宏。
八、auto 关键字
auto 关键字的作用是在创建变量的时候根据赋值表达式的类型推断出变量的类型。
当变量的类型复杂时,使用 auto 关键字非常方便且不易出错。
1. auto 关键字的使用
// 头文件
#include <iostream>// 使用声明
using std::cout;
using std::endl;int main()
{auto a = 1; // intauto b = 1.1; // doubleauto c = 'a'; // char auto d = "aaaaa"; // const char*auto e = 1 + 1.1; // doublereturn 0;
}
从上述代码中的最后一条 auto 赋值语句中可以得出,auto 语句是根据表达式的值进行类型推断的。
2. auto 关键字使用的注意事项
1)在早期的 C/C++ 中,auto 关键字修饰的变量是具有自动存储器的局部变量。由于在函数中默认创建的变量就是局部变量,所以导致该关键字几乎没人使用。所以,C++11 标准赋予该关键字根据赋值表达式推断类型的能力。
2)使用 auto 关键字必须对变量初始化,因为 auto 关键字需要根据表达式的类型来推断该变量的类型。因此 auto 并非是一种类型声明,而是一个类型声明时的占位符,编译器在编译器会把 auto 替换为该变量对应的类型。
3)用 auto 声明指针类型时,使用 auto 和 auto* 没有任何区别,只是后者显示表示该类型是个指针。
4)用 auto 声明引用类型时必须使用 auto&。
5)使用 auto 在一行定义多个变量时,这些变量的基本类型必须相同。如:int、int*、int&,它们的基本类型都是 int。
6)auto 不能用来作为函数参数,也不能直接用来声明数组。
九、基于范围的 for 循环
范围 for 是 C++11 新增的一种遍历方法,for 后面的圆括号被冒号(:)分为两部分,前者是范围内用于迭代的变量,后者是被迭代的范围。
迭代的变量被依次赋予迭代范围中的值,所以正常情况下只能读取数据,就相当于把范围中的值依次拷贝到迭代的变量中。所以一般情况下使用引用,这样既减少了拷贝的环节,又可以修改范围中的数据。当只需要读取数据时,前面加上 const 即可。
1. 范围 for 的使用
// 头文件
#include <iostream>// 使用声明
using std::cout;
using std::endl;// 常量声明
const int SIZE = 10;int main()
{int arr[SIZE];for (int i = 1; i <= 10; ++i)arr[i - 1] = i;// 使用范围 for 变量数组for (auto& elem : arr){cout << elem << " ";elem *= 2;}cout << endl;for (auto& elem : arr)cout << elem << " ";return 0;
}
代码的运行结果如下:
与普通的循环一样,可以使用 continue 或者 break 跳出循环。
2. 范围 for 的使用条件
1)迭代的范围必须是确定的,如数组就是第一个元素到最后一个元素;
2)迭代的对象要实现++和==的操作。(范围 for 的本质是迭代器)
十、空指针 nullptr(C++11)
在 C 语言中,空指针使用 NULL 表示。但是在 C++ 中,NULL 是一个宏,即 #define NULL 0。所以它的本质是数字 0,而在 C++ 中,关键字 nullptr 代表空指针。如下代码:
// 头文件
#include <iostream>// 使用声明
using std::cout;
using std::endl;// 函数定义
void func(int)
{cout << "func1(int)" << endl;
}void func(int*)
{cout << "func2(int*)" << endl;
}int main()
{func(0);func(NULL);func(nullptr);
}
代码运行结果如下:
可以看到当函数重载既有 int 参数又有指针参数时,NULL 会优先使用 int 参数的函数。所以在 C++ 中,尽量使用 nullptr 作为空指针。
&esmp;首先,nullptr 是 C++ 的关键字,使用时不需要包含头文件。且在 C++11 中,sizeof(nullptr) 和 sizeof((void*)0) 的结果相同。
相关文章:

《深入探究:C++ 在多方面对 C 语言实现的优化》
目录 一、C 在 C 上进行的优化二、C 关键字(C 98)三、C 的输入输出1. cin 和 cout 的使用2. cin、cout 和 scanf()、printf() 的区别 三、命名空间1. 命名空间的使用2. 嵌套命名空间3. 在多个头文件中使用相同的命名空间 四、函数缺省值1. 缺省值的使用2…...

React 第十六节 useCallback 使用详解注意事项
useCallback 概述 1、useCallback 是在React 中多次渲染缓存函数的 Hook,返回一个函数的 memoized的值; 2、如果多次传入的依赖项不变,那么多次定义的时候,返回的值是相同的,防止频繁触发更新; 3、多应用在 父组件为函…...

使用C#和OPenCV实现圆形检测
文章目录 霍夫变换使用 OpenCV 和 C# 实现圆形检测 霍夫变换 在计算机视觉中,圆形检测是一个常见且有用的任务,特别是在物体识别、图像分析和图形处理等领域。OpenCV 是一个强大的开源计算机视觉库,它提供了许多工具来实现不同的图像处理功能…...

评估一套呼叫中心大模型呼入机器人的投入回报比?
评估一套呼叫中心大模型呼入机器人的投入回报比? 原作者:开源呼叫中心FreeIPCC,其Github:https://github.com/lihaiya/freeipcc 评估一套呼叫中心大模型呼入机器人的投入回报比(ROI),是一个多…...

十八、Label 和 Selector
Label 是键值对,用来标识 Kubernetes 资源(如 Pod、Node、Service 等)的属性。它们并不直接影响资源的行为,但可以帮助用户快速组织、查询和操作这些资源。标签可以用于选择、过滤和分组。 Label: 标签对 k8s 中各种资源进行分类、分组,如Pod和节点进行分组。通过添加kev…...

实现按键按下(低电平)检测到下降沿
按照流程进行编程 步骤1: 初始化函数 包括时基工作参数配置 输入通道配置 更新中断使能 使能捕获、捕获中断及计数器 HAL_TIM_IC_Init(&ic_handle) //时基参数配置 HAL_TIM_IC_ConfigChannel(&ic_handle,&ic_config,TIM_CHANNEL_2) //输…...

解析 SSM 垃圾分类系统,助力生态平衡
前 言 垃圾分类系统,传统的垃圾分类系统模式还处于线下管理阶段,管理效率极低。随着垃圾分类系统信息的不断增多,传统基于线下管理模式已经无法满足当前用户需求,随着信息化时代的到来。通过该系统的设计,管理员可以管…...

软件工程 设计的复杂性
复杂性代表事件或事物的状态,它们具有多个相互关联的链接和高度复杂的结构。在软件编程中,随着软件设计的实现,元素的数量以及它们之间的相互联系逐渐变得庞大,一下子变得难以理解。 如果不使用复杂性指标和度量,软件…...

Nginx 限制只能白名单 uri 请求的配置
实际生产项目中,大多数时候我们会将后端的 http 接口通过前置 nginx 进行反向代理,对互联网用户提供服务。往往我们后端服务所能提供的接口服务是大于互联网用户侧的实际请求的接口地址数量的(例如后端服务一共有100个api接口,经过…...

QT c++ 同时使用sqlite 和mysql数据库的问题
在项目开发中,同时使用了sqlite 和mysql数据库,分开这两部分运行功能都正常,但是一起运行,就异常,sqlite部分不能使用。 现象:出现如下提示 QSqlDatabasePrivate::addDatabase: duplicate connection nam…...

redis集群 服务器更换ip,怎么办,怎么更换redis集群的ip
redis集群 服务器更换ip,怎么办,怎么更换redis集群的ip 1、安装redis三主三从集群2、正常状态的redis集群3、更改redis集群服务器的ip 重启服务器 集群会down4、更改redis集群服务器的ip 重启服务器 集群down的原因5、更改redis集群服务器的ip后…...

【C++习题】19.数组中第K个大的元素
题目:数组中第K个大的元素 链接🔗:数组中第K个大的元素 题目: 代码: class Solution { public:int findKthLargest(vector<int>& nums, int k) {// 将数组中的元素先放入优先级队列中priority_queue<i…...

JIS-CTF: VulnUpload靶场渗透
JIS-CTF: VulnUpload来自 <https://www.vulnhub.com/entry/jis-ctf-vulnupload,228/> 1,将两台虚拟机网络连接都改为NAT模式 2,攻击机上做namp局域网扫描发现靶机 nmap -sn 192.168.23.0/24 靶机IP地址192.168.23.162,攻击机IP地址192.168.23.140…...

BGP-面试
简单介绍一下BGP BGP,边界网关协议,属于路径矢量路由协议。属于触发式更新或者增量更新。具有丰富的路由策略,能够灵活的进行路由选择。重心不是在路由学习,而是路由优选、更高效的传递路由和维护大量的路由信息。基于TCP…...

Git-安装与常用命令
目录 1.Git环境配置 1.1下载 1.2配置 1.2.1基本配置 1.2.2常用指令配置别名 1.2.3获取本地仓库 git命令在git bash中演示,会用到一些Linux命令。 1.Git环境配置 1.1下载 Git下载地址:https://git-scm.com/download 傻瓜式安装就可以了。 安装…...

回归预测 | Matlab实现基于BiLSTM-Adaboost双向长短期记忆神经网络结合Adaboost集成学习回归预测
目录 效果一览基本介绍模型设计程序设计参考资料效果一览 基本介绍 回归预测 | Matlab实现基于BiLSTM-Adaboost双向长短期记忆神经网络结合Adaboost集成学习回归预测 模型设计 基于BiLSTM-Adaboost的回归预测模型结合了双向长短期记忆神经网络(BiLSTM)和Adaboost集成学习的…...

微信小程序跳转其他小程序以及跳转网站
一、跳转其他小程序 1.1 知道appid和页面路径 wx.navigateToMiniProgram({appId: appid, // 替换为目标小程序 AppIDpath: pathWithParams, // 小程序路径envVersion: release, // 开发版、体验版或正式版success(res) {console.log("跳转到其他小程序成功!&q…...

Not using native diff for overlay2, this may cause degraded performance……
问题现象 案例:Anolis 8.9(4.19.91-26.an8.x86_64) Overlay2存储驱动程序) 当我们安装好Docker之后,通过systemctl status docker -l 会发现有一个告警信息:levelwarning msg"Not using native dif…...

【自用】管材流转项目 数据库恢复之 PIPE 表 二维码相关 各个表恢复 SQL
总览 1.后端前端和数据库 PIPE 页面的关系 2.后端批量生成二维码 jpg 图片 3.为了保证 PIPE 正常使用的调整 4.TRANSFORM(流转表) 一、后端前端和数据库 PIPE 页面的关系 1.前端 关于PIPE页面,首先,在前端,我们已经…...

【渗透测试】信息收集二
其他信息收集 在渗透测试中,历史漏洞信息收集是一项重要的工作,以下是相关介绍: 历史漏洞信息收集的重要性 提高效率:通过收集目标系统或应用程序的历史漏洞信息,可以快速定位可能存在的安全问题,避免重复…...

测试工程师八股文04|计算机网络 和 其他
一、计算机网络 1、http和https的区别 HTTP和HTTPS是用于在互联网上传输数据的协议。它们都是应用层协议,建立在TCP/IP协议栈之上,用于客户端(如浏览器)和服务器之间的通信。 ①http和https的主要区别在于安全性。http是一种明…...

定时/延时任务-Kafka时间轮源码分析
文章目录 1. 概要2. TimingWheel2.1 核心参数2.2 添加任务2.3 推进时间 3. TimerTaskList3.1 添加节点3.2 删除节点3.3 刷新链表3.4 队列相关 4. 时间轮链表节点-TimerTaskEntry5. TimerTask6. Timer 和 SystemTimer - 设计降级逻辑7. 上层调用8. 小结 1. 概要 时间轮的文章&a…...

如何用状态图进行设计05
到目前为止,我们已经讨论了状态图的原理。这些原理对状态图和扩展状态图都适用。第二章后面的部分主要讲述了扩展状态图的扩展功能。我们将围绕这些增强的功能,使你对BetterState Pro的设计能力有很好的了解。 关于这些内容和其他有关扩展状态图特性的完…...

【计算机视觉】边缘检测
图像的边缘简单来说就是图像中灰度不连续的地方。 1.图像梯度 图像梯度是指图像像素灰度值在某个方向上的变化;图像梯度是图像的一阶导数,实际计算时可以使用差分来近似。 1.1 什么是图像梯度? 图像梯度是一种数学工具,用于描…...

林曦词典|无聊
“林曦词典”是在水墨画家林曦的课堂与访谈里,频频邂逅的话语,总能生发出无尽的思考。那些悠然轻快的、微妙纷繁的,亦或耳熟能详的词,经由林曦老师的独到解析,意蕴无穷,让人受益。于是,我们将诸…...

LabVIEW光栅衍射虚拟仿真系统
随着现代教育技术的快速发展,虚拟仿真实验平台逐渐成为物理实验教学的重要辅助工具。基于LabVIEW的平面透射光栅虚拟仿真系统帮助学生更好地理解和分析光栅衍射现象,提高教学质量和学生的学习兴趣。 项目背景 在波动光学的教学中,光栅衍射实…...

【NumPy进阶】:内存视图、性能优化与高级线性代数
目录 1. 深入理解 NumPy 的内存视图与拷贝1.1 内存视图(View)1.1.1 创建视图1.1.2 视图的特点 1.2 数组拷贝(Copy)1.2.1 创建拷贝1.2.2 拷贝的特点 1.3 视图与拷贝的选择 2. NumPy 的优化与性能提升技巧2.1 向量化操作示例&#x…...

从YOLOv5到训练实战:易用性和扩展性的加强
文章目录 前言一、模型介绍二、YOLOv5网络结构1.Input(输入端):智能预处理与优化策略2.Backbone(骨干网络):高效特征提取3.NECK(颈部):特征增强与多尺度融合4.Prediction…...

Prim 算法在不同权重范围内的性能分析及其实现
Prim 算法在不同权重范围内的性能分析及其实现 1. 边权重取值在 1 到 |V| 范围内伪代码C 代码实现2. 边权重取值在 1 到常数 W 之间结论Prim 算法是一种用于求解加权无向图的最小生成树(MST)的经典算法。它通过贪心策略逐步扩展生成树,确保每次选择的边都是当前生成树到未加…...

canal安装使用
简介 canal [kənl],译意为水道/管道/沟渠,主要用途是基于 MySQL 数据库增量日志解析,提供增量数据订阅和消费 工作原理 canal 模拟 MySQL slave 的交互协议,伪装自己为 MySQL slave ,向 MySQL master 发送 dump 协议…...