《c++ primer笔记》第二章 变量和基本类型

news2024/11/19 18:41:38

前言

最近开始二刷c++ primer,第一遍很模糊的过了一下,由于前面的基础很多没理解透,从12章到16章基本是懵逼的状态。第二次为了保证质量准备把每个章节个人感觉重要的部分进行一个记录与总结,其中也记录了部分看书过程中遇到的问题,欢迎大佬们讨论。

文章目录

    • 一、基本内置类型
      • 1.1基本概念
      • 1.2类型转换
    • 二、变量
      • 2.1初始化
      • 2.2变量声明和定义的关系
    • 三、复合类型
      • 3.1引用
      • 3.2指针
    • 四、const限定符
      • 4.1const的引用
      • 4.2指针和const
      • 4.3顶层const
      • 4.4constexpr和常量表达式
    • 五、处理类型
      • 5.1类型别名
      • 5.2auto类型说明符
      • 5.3decltype类型

一、基本内置类型

1.1基本概念

​ C++包含算术类型空类型两种基本数据类型。算术类型包含字符、整型数、布尔值和浮点数;空类型不对应具体的值,常见的比如写一个void的函数。下图是算术类型的表格,不同类型所占比特数不同,它们可以表示的范围也不一样。long long是C++11的新特性。对于浮点型,float和double分别有7和16个有效位。

image-20230110144224712

带符号和无符号类型

​ 如果把布尔型和扩展的字符型除去,整形可以划分为带符号无符号两种。带符号类型可以表示正数、负数或0,而无符号类型仅能表示大于等于0的数。在有符号类型int、short等前面加上unsigned就可以变成无符号类型,unsigned int可以直接缩写为unsigned。对于字符型:char、signed char和unsigned char。char和signed char并不一样,所以字符的表现形式只有两种,char具体怎么表示由编译器决定。一般来说,两种类型最明显的区别就是它们所能表示的范围,对于一个8比特的有符号char,所能表示范围为-128-127,而无符号char范围则为0-255。

如何选择类型

​ 书上写得很详细,对于初学者更应该关注前期如何合理、规范的定义类型。

  • 明确数值不为负,选择无符号类型
  • 尽量使用int,short太小,而long long太大,除非明确知道需要的范围超过了int。
  • 尽量不使用char,因为在不同的机器上是否带符号是不确定的,如果要使用也要必须指定类型。
  • 浮点数优先选择double,不仅精度高而且计算代价和单精度相比也相差无几。

1.2类型转换

​ 当一种类型由于某些需要主动/被动转换成了另一种形式就是发生了类型转换。类型所能表示的值的范围决定了转换的过程:一个布尔值转换为整形,false->0,true->1;浮点型转换为整形,小区部分记为0并保留整数部分。转换的时候比如考虑当前类型所能表示的范围,当一个无符号类型被赋予了一个超出范围的数,那么最后得到的结果是对无符号类型表示范围总数取模后的余数对于有符号类型表示的数超出范围将是未定义的

当表达式中含有无符号类型

​ 前面说过,类型转换的操作可以是主动也能是被动,在一段表达式中,如果同时出现一个有符号整数和无符号整数,那么有符号数就会进行主动转换成无符号数进行计算。在第二个表达式中,b是一个有符号整数,所以首先应该把它转换成无符号类型再进行计算,a和b相加后再对232取模(对这个取模感觉有点问题,要得到下面的结果,也可以直接a加上b后为-32,232 = 4294967296,那么用4294967296 - 32就得到了结果,取模反而不对,换成其它数字也能得到正确的结果,可能我哪儿理解有问题)。

unsigned a = 10;
int b = -42;
cout << b + b << endl; // -84
cout << a + b << endl; // 4294967264 这里的int是32位
/*
a = 10
b = -42 转换为无符号 (4294967296 - 42)= 4294967254
b = 4294967254 现在b也是无符号类型
a + b = 4294967264
*/

​ 思考很久没有搞懂,问别人直接一句用二进制看就醒悟了,看来以前学的计算机基础全没了,要知道整数在计算机中是由补码来存储的,比如对于8比特大小的-1,[-1] = [1000 0001]原 = [1111 1110]反 = [1111 1111]补,看最后的补码,由于转换成了无符号数,那么该二进制的结果就是255。如果要快速算可以参考上面代码块b=-42的转换过程。

​ 平时在写表达式时一定要确定变量的类型,否则出现如上面表达式的转换往往会找不到的出错的原因,特别是绝对不要用无符号类型写for循环的判定值,否则该循环会无休止的执行下去,当然如果坚持要用也可以通过使用while的方式解决。

二、变量

​ 数据类型决定着变量所占内存空间的大小和布局方式、该空间能存储的值的范围,以及变量能参与的运算。对象是指一块能存储数据并具有某种类型的内存空间,而命了名的对象就叫做变量。

2.1初始化

​ 初始化就是一个对象获得了一个特定的值,这里要注意初始化并不是赋值,初始化的含义是创建对象赋予其一个初始值,而赋值的含义是把当前对象的值移除,而以一个新值来替代。

列表初始化

​ 这是C++11的新特性,通过花括号的方式使用:int a{1};,但是这种方式存在丢失信息的风险,下面的代码在编译器中会报错。

long double a = 3.1123123123123;
int b{a}; // 错误。由于存在丢失信息的风险,转换未执行

默认初始化

​ 没有指定初值的变量将会进行默认初始化,默认值的类型由变量类型决定。定义在函数体外的变量会被默认初始化为0,而内部的内置类型不会被初始化,建议初始化每一个内置类型的变量。

2.2变量声明和定义的关系

​ C++支持分离式编译机制,该机制允许将程序分割为若干个文件,每个文件可被独立编译。为了支持分离式编译,C++将声明和定义区分开,声明就是告诉程序一个名字,定义就是去设计这个名字的具体内容并把它们关联起来,如果要声明一个变量而非定义它,可以在前面加一个关键字extern,并且声明是不能初试化的,否则就成了定义。

extern int i; // 声明
int j; // 定义

extern int i = 23; // 报错

对于实际的情况,我们可以在多个文件中声明同一个变量,但是定义该变量只能在一个文件中。

三、复合类型

​ 引用和指针是常见而重要的两中复合类型。

3.1引用

在C++中,谈到引用时一般指‘左值引用’,C++11中新增了右值引用,一般用于内置类型。引用其实就是给一个对象起了另外一个名字,并且引用必须初始化,这是因为在定义引用时,程序将和它的初始值对象一直绑定在一起,所以一个引用也无法被绑定到另外一个对象上。

int a = 123;
int &b = a; // b是a的另外一个名字
int &c; // 报错,引用必须初始化

定义了引用后,所有的操作都会影响到引用绑定的对象

b = 2;
cout << a << end; // 2

如果用引用来初始化另一个引用,相当于就是把该引用绑定的对象作为初始值。

int &d = b; // d和b都是a的名字

由于引用本身不是一个对象,所以不能定义引用的引用,所以引用只能绑定到对象上,不能与字面值或某个表达式的计算结果绑定在一起。

3.2指针

​ 类似于引用,指针也实现了对其他对象的间接访问,但是指针存在几点不同。1)指针本身是一个对象,同时它可以在生命周期类指向不同的对象。2)定义指针无需初始化。

​ 定义指针就是把声明符写成*d的形式,指针实际存储的是一个对象的地址,要想获得地址,需要使用&,而要想访问指针指向的对象,需要使用解引用符*

int a = 12;
int *p = &a // p存放a的地址,或者说p是指向a的指针
int *q = p; // q的初始值为指向a的指针
*p = 123; // 相当于a = 123

​ 指针同样有空值,可以通过下面三种方式初始化一个空指针。nullptr字面值是在C++11中引入。虽然NULl = 0,但是在定义指针是不能出现int a = 0, p3 = a 这样的表达式,也就是不能把int变量直接赋值给指针,即使该值为0。

int *p1 = nullptr; // 字面值形式
int *p2 = 0; // 字面值形式
int *p3 = NULL; // 预处理变量,相当于0,使用它需要包含头文件cstdlib

​ 前面在讲引用的时候说过,由于引用本身并不是一个对象,所以引用在绑定了一个对象后就不会再改变,而指针就不一样,它可以随时更换自己指向的对象。

void*

​ void*是一种特殊的指针,可以用于存放任意对象的地址。一般来说该指针使用较少,因为我们不知道它指向的对象是什么类型,也就不能直接操作void *指向的对象。

小结

  • 指针和引用

    ​ 指针和引用都是符合类型,指针‘指向’内存中的某个对象,而引用‘绑定到’内存中的某个对象,它们都实现了对其他对象的间接访问。它们的区别有:引用本身不是一个对象,并且在定义时必须初始化,同时引用只要一开始绑定了一个对象那么后续就不能再改变。指针本身是一个对象,所以允许对指针赋值和拷贝,定义时可以不用初始化,并且在它的生命周期内,一个指针可以绑定多个对象。

指向指针的指针

​ 指针本身是一个对象,所以它有自己的地址,那么肯定也接受另一个指针指向自己,也就是指向指针的指针。

int a = 123;
int *p = &a;
int **p2 = &p; // 指向指针的指针

​ 下图描述了上面代码变量之间的关系,如果解引用一个指向指针的指针就会得到一个指针

image-20230111160425482

指向指针的引用

引用不是一个对象,所以不存在指向引用的指针。

int i = 42;
int *p; // p是一个指针
int *&r = p; // r是一个对指针p的引用,从右往左解读,首先r左边是&,那么r是一个引用,然后跟着一个*,那么说明r引用的是一个指针。

r = &i; // r引用了指针p,也就是r是p的另外一个名字,所以这里相当于让p指向i
*r = 0; // 同理,解引用r就是解引用p,那么现在i的值为0

四、const限定符

​ 通过const修饰的变量在程序的执行过程中不能被改变,所以一旦使用const就必须要初始化。同时const变量也能和普通变量一样参与算术运算、赋值、转化等操作,也就是说只有当要改变改变量时const限定符才会发挥作用。一般来说一个const变量的作用域只存在于一个文件中,多个文件即使定义同名的const变量,它们也是独立的。那么如果我们希望一个const变量能够在多个文件中共享,可以使用关键字extern

t1.h
extern const int f = 1024; // 在一个文件中定义
t2.cpp
extern const int f; // 其它文件进行声明,两个文件的f是同一个

4.1const的引用

​ 又称为常量引用。const常量也能被引用,与普通的引用不同,我们不能通过引用去改变它所绑定对象的值。

const int a = 123;
const int &r = a;
r = 32; // 错误
int &r1 = a; // 错误,非常量引用不能绑定到一个常量对象上

​ 前面引用提到,引用的类型必须与所引用的对象一致,这里有两种例外。1)只要在初始化常量引用时=右边的结果可以主动转换为引用的类型。2)一个常量引用可以绑定到非常量的对象、字面值或者一般表达式。下面的例子中,我们定义了一个常量引用r1绑定到一个非常量对象val上,并且它们的类型也不同,但是这里并不会报错。

double val = 3.14;
const int &r1 = val;

​ 其实在编译器内部,会首先声明一个临时的整形变量(临时量:编译器需要一个空间来存储表达式的结果而临时创建的一个未命名的对象),然后再把r1绑定到这个临时量上。

// 编译器内部的操作
const int temp = val; // val由double转换为int,进行了窄化
const int &r1 = temp;

​ 如果我们通过非常量引用int &r2 = val,就会直接报错,继续上面的一个过程,既然定义了一个非常量引用r2,就说明可能会改变它所绑定的对象,而在编译器的处理过程中,r2会绑定到一个临时变量上,所以通过r2也就只能改变临时变量的值,而val不会被影响,所以C++视这种把非常量引用绑定到临时量上为非法操作

4.2指针和const

​ 指向常量的指针不能用于改变所指对象的值,存放常量对象的地址只能使用指向常量的指针。与常量引用类似,指向常量的指针可以指向一个非常量的对象。

const int a = 123;
const int *p = &a; // p不能改变a的值

const指针

​ 使用常量指针必须进行初始化,也就是该指针指向的对象在以后无法改变,但是任然可以通过该指针修改指向对象的值。下面是定义方式。

int a = 12
int *const p = %a; // p指针将一直指向a

​ 继续套娃,可以写一个指向常量指针对象的常量指针,这样一来,不仅常量指针p不能指向其它对象,且无法通过它改变b的值。

const int b = 213;
const int *const p = &b;

4.3顶层const

​ 顶层const的含义表示指针本身是个常量,与它相反的底层const表示指针所指的对象是一个常量。一般来说,顶层const可以表示任意的对象是常量,使用与任何类型;底层const则与指针和引用等符合类型的基本类型部分有关。指针类型既可以是顶层const也可以是底层const。(第一次看的时候有点模糊,简单来说就是一个变量,如果自己不能改变就是顶层const,如果该变量时指针,它指向的对象不能改变而自己可以改变就是底层const,可以看看书上的例子。)

int i = 0;
int *const p1 = &i; // p1是一个常量指针,自己不能改变所以是顶层const
const int *p2  = &i; // p2是一个指向常量的指针,虽然不能通过它改变i的值,但是它自己可以指向其它对象,所以这是一个底层const
const int *const p3 = &p2; // p3是一个指向常量的常量指针,所以同时拥有顶层const和底层const

在进行拷贝操作时,顶层const不受影响,而底层const存在限制:拷入和拷出的对象必须具有相同的底层const资格。或者说两个类型能够转换,一般来说非常量可以转换成常量,反之不行。

int *p = p3; // 错误,p3含有底层const而p没有。可以这样理解,p3也含有顶层const,也就是说它本身是常量不能改变,如果我们定义一个普通指针p指向p3,那么就说明可以通过p去改变p3的值,产生了矛盾。

​ 总的来说,判断一个表示是否可行如果按照定义其实还挺麻烦,我觉得只要把每个变量是否是常量搞清楚,是常量就不能用普通指针或引用去指向它。下面有两道例题2.30、2.31。

4.4constexpr和常量表达式

​ 常量表达式指值不会改变且在编译过程就能得到计算结果的表达式。字面值就一个常量表达式。

const int a = 20; // 常量表达式
const int b = a + 1; // 常量表达式
int c = 23; // 非常量表达式
const int d = fn(); // 非常量表达式

constexpr变量

C++11新增,允许将变量声明为constexpr类型以便由编译器来验证变量的值是否是一个常量表达式。【代码风格:如果认定一个变量是一个常量表达式,声明的时候就使用constexpr】

constexpr int a = 20; // 20是一个常量表达式,所以a是常量表达式
constexpr int b = fn(); // 只有当fn是一个constexpr函数时,b才是一个常量表达式

字面值类型

​ 目前为止,算术类型、引用和指针都属于字面值类型,而像自定义类、IO库、string类型则不属于字面值类型,也就不能被定义为constexpr。一个constexpr指针的初试值必须为nullptr或0,或者存储于某个固定地址中的对象

指针和constexpr

​ constexpr声明一个指针仅对指针有效,而不影响所指的对象。对于下面两个指针p和q,p是一个指向常量的指针,而q是一个常量指针,相当于int *const q = nullptr关键在于constexpr把定义的对象置为顶层const

const int *p = nullptr;
constexpr int *q = nullptr;

例题

​ 书上有一些考察引用和指针的例题,可以巩固一下上面的内容。

image-20230111195537963

a是非法的,因为非常量引用不能绑定到字面值上【见3.1】。
b,c,d,e,g都是合法的
f是非法的,既然是定义一个常量指针,那么就必须初始化

image-20230111202628349

2.30)

v2是顶层const,因为它是一个常量
p2是底层const,它不能改变指向对象的值,自己可以改变
p3即是顶层const也是底层const
r2是底层const

2.31)

r1 = r2正确,虽然r2不能去改变v2的值,但是只赋值给r1不会有任何影响

p1 = p2 错误,p2是一个常量指针,不能修改v2的值,如果让一个普通指针p1指向p2,就说明可以通过p1去修改v2的值,产生矛盾。

p2 = p1正确,p2是底层const,自己可以改变。

p1 = p3 错误,与p1 = p2错误同理。

p2 = p3 正确。

五、处理类型

5.1类型别名

typedef是传统定义类型别名的关键字,含有typedef的声明语句定义的不再是变量而是类型别名。C++11规定一个新的别名声明方法using

typedef int hh; // hh a = 12 就相当于 int a = 12;
using hh = int; // 和上面一样的效果

5.2auto类型说明符

​ 平常我们要接受一个值必须要知道它的类型,然后声明一个变量去接收,如果使用auto,编译器就可以根据值来推算类型,不需要我们再去声明类型,同时注意使用auto定义的变量必须有初始值。在使用auto声明多个变量时一定要保证这些变量的初始值是同类型的。

复合类型、常量和auto

​ 在使用指针和引用时,实际操作的都是背后指向的对象,auto就会根据该对象的类型来给出结果。auto会忽略掉顶层const,如下,b和c都直接忽略了a的顶层const,注意d对一个常量对象取址是一种底层const

const int a = 1, &r = a;
auto b = a; // b是一个整数
auto c = r; // c是一个整数

auto d = &a; // 对一个常量对象取址是一种底层const,所以d一个指向整数常量的指针

如果想要保留顶层const,只需要在声明类型前加一个const就行。

const auto b = a; // b是一个整形常量

auto用作引用时可以保留顶层const。

auto &e = a; // e是一个常量引用
auto f = 23; // 23是字面值,而非常量引用不能绑定到字面值上
const auto &j = 32; // j是常量引用,可以绑定字面值32

5.3decltype类型

​ 使用auto时编译器会根据表达式的类型推断出定义变量的类型并且用表达式结果初试化,如果我们只需要得到表达式的类型而不需要初始化,就可以使用C++11引入的decltype

decltype(f()) sum = x; // sum的类型就是函数f的返回类型

decltype在处理顶层const与auto不同,如果decltype使用的表达式是一个变量,那么直接返回该变量的类型(包括顶层const和引用)

const int a = 0, &r = a;
decltype(a) x = 0; // x是const int
decltype(r) y = x; // y是const int &

decltype和引用

​ 如果decltype表达式不是一个变量,则返回表达式结果对应的类型。下面的两个表达式中decltype(r)结果是引用类型,但是r + 0结果是一个具体值也就是int类型。第二表达式中,decltype使用解引用就会得到引用类型,所以最后的结果是int &而不是int

int i = 42, *p = &i, &r = i;
decltype(r + 0) b; // b是int
decltype(*p) c; // 对p解引用得到的应是int &,所以这里错误,引用必须初始化

decltype的结果与表达式的关系非常密切,对于decltype所用表达式,变量名添上一对括号就有不同的结果,因为变量是一种可以赋值语句左值的特殊表达式,这样的decltype的结果会是引用

decltype(i) d; // d是一个未初始化的int变量
decltype((i)) c; // (i)是一个表达式,结果类型为引用,没有初始化将会报错

小结

  • decltypeauto的区别
    1. auto用编译器计算变量的初始值来推断其类型,而decltype只计算类型,而不计算表达式的值decltype(a = b)中,a的值并不会改变,只会得到一个int&类型。
    2. 编译器推断出的auto类型有时候与初始值类型不完全一样,存在忽略顶层const,而decltype则会保留。
      达式的关系非常密切,对于decltype所用表达式,变量名添上一对括号就有不同的结果,因为变量是一种可以赋值语句左值的特殊表达式,这样的decltype的结果会是引用
decltype(i) d; // d是一个未初始化的int变量
decltype((i)) c; // (i)是一个表达式,结果类型为引用,没有初始化将会报错

参考书籍
《C++ Primer 第五版》

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

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

相关文章

[JS]JavaScript基础学习笔记(黑马pink+尚硅谷李立超)

文章目录&#x1f97d; 前言&#x1f97d; JavaScript 简介&#x1f30a; JavaScript 是什么&#x1f30a; JavaScript 的作用&#x1f30a; HTML/CSS/JS 的关系&#x1f30a; 浏览器执行 JS&#x1f30a; JS 的组成&#x1f97d; JavaScript 的书写位置&#x1f30a; 行内式 J…

【C语言】指针进阶(一)

学好指针✊✊✊还有&#xff0c;男孩子在外面要保护好自己一、字符指针字符也有地址&#xff0c;当然可以将其储存——字符指针&#xff0c;是储存字符地址的指针对于普通的单个字符&#xff1a;char ch a;char* pc1 &ch;这里的pc是单个变量ch‘&#xff08;单个字符&…

防火门监控系统在智能建筑消防的重要性及应用介绍

【摘要】&#xff1a; 安全、舒适的生活及办公环境是人们所追求的&#xff0c;因此&#xff0c;在建筑中各种智能化的设备及布控系统显得尤为重要。近年各种频发的高危火灾事件严重威胁到了国民的生命安全&#xff0c;所以火灾监控系统在建筑中的应用显得尤为重要。本文主要从智…

【涵子来信python大全】——第二季——opencv第一篇

各位亲爱的读者&#xff0c;博主&#xff1a; 首先恭喜大家&#xff0c;涵子来信已经到达第二季——2023年篇。今天&#xff0c;我们要步入机器学习的初级内容&#xff1a;python opencv图片&#xff01; 目录 一、提前准备 二、程序代码学习 2.1.如何读取图片 2.2.显示图…

MySQL架构,以及redo log、undo log和binlog的区别(六)

一、Mysql的基本架构图 二、连接器 连接器负责跟客户端建立连接&#xff0c;获取权限、维持和管理连接&#xff1a; 用户名密码验证&#xff1b;查询权限信息&#xff0c;分配对应的权限&#xff1b;可以使用show processlist查看现在的连接&#xff1b;如果太长时间没有动静…

【rt-thread网络】第0篇:使用paho-mqtt软件包连接腾讯云mqtt服务器

文章目录一、mqtt介绍二、paho mqtt介绍三、连接腾讯云的步骤3.1 在腾讯云控制台的IOT HUB创建产品和设备&#xff08;略&#xff09;3.2 根据产品信息填充MQTTClient的连接参数3.3 编译和下载到开发板&#xff08;略&#xff09;四、测试五、参考一、mqtt介绍 MQTT(消息队列遥…

【Linux操作系统】如何实现Linux中软件安装进度条?

文章目录一.回车与换行二.缓冲区问题三.倒计时小程序四.进度条小程序Linux下安装软件时&#xff0c;经常会看到类似上图的进度条&#xff0c;今天带大家用C语言来演示其原理&#xff01; 一.回车与换行 俗话&#xff1a;回车换行&#xff0c;实际是回车和换行的组合 回车是回…

助力工业物联网,工业大数据项目之数据采集

文章目录01&#xff1a;Sqoop命令回顾02&#xff1a;YARN资源调度及配置03&#xff1a;MR的Uber模式04&#xff1a;Sqoop采集数据格式问题05&#xff1a;问题解决&#xff1a;Avro格式06&#xff1a;Sqoop增量采集方案回顾01&#xff1a;Sqoop命令回顾 目标&#xff1a;掌握Sqo…

TypeScript环境搭建 下载/安装 ,编译运行的三种方式:tsc命令行/tsc-node库/webpack搭建环境

目录 什么是TypeScript? 首先来进行全局安装 &#xff1a; 编译运行 方式一&#xff1a;命令行(cmd终端)--->tsc命令行 1.将代码编译为JavaScript的代码&#xff0c;使用cmd终端或者命令行运行以下命令&#xff1a; 2.在浏览器或者Node环境下运行JavaScript代码 方式…

声纹识别与声源定位(一)

针对目前智能计算机及大规模数据的发展&#xff0c;依据大脑处理语音、图像数据方法的deep learning技术应运而生。deep learning技术是应用于音频信号识别&#xff0c;模仿大脑的语音信号学习、识别的模式。在音频信号处理的过程中&#xff0c;运用deep learning进行音频数据的…

极海APM32F072RB开发环境测试

极海APM32F072RB开发环境测试通过自制的开发板进行测试。 &#x1f3ac;基于STM32cubemx工程配置 Keil MDK编译 ST-LINK/V2烧录 &#x1f33b;基于APM32F0xx_SDK Keil MDK编译 ST-LINK/V2烧录 &#x1f33f;官方的SDK包下载地址&#xff1a;https://www.geehy.com/support/…

DMDW主备集群搭建备库先open引发的问题

一、问题描述及配置主备集群搭建成功后&#xff0c;主备库启动脚本中START_MODEmount&#xff0c;备库的lsn号大于等于备库&#xff0c;N_OPN打开次数主库大于备库。假如搭建主备集群后&#xff0c;备库首先OPEN一下后引发的问题如下图&#xff1a;启动脚本中START_MODEopen3、…

tcp紧急指针,mss,rto,零窗口探测等

三次握手、四次挥手、重传机制、滑动窗口、流量控制、拥塞控制、TCP/UDP全解析-蒲公英云 (dandelioncloud.cn)(511条消息) TCP零窗口探测_redwingz的博客-CSDN博客_tcp0窗口TCP系列32—窗口管理&流控—6、TCP zero windows和persist timer - 走看看 (zoukankan.com)TCP协议…

VUE-Axios-解决跨域问题.

vue-axios跨域问题发现: https://github.com/Aealen/TopicSelection-VUE 使用vue-axios向后端发送请求的时候遇到如下报错: vue-axios跨域问题原因: 什么是跨域 **跨域&#xff1a;**指的是浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的&#xff0c;是浏览器…

从零开始编写一个上位机(串口助手)QT Creator + Python

提示&#xff1a;本博客作为学习笔记&#xff0c;有错误的地方希望指正&#xff0c;此文可能会比较长&#xff0c;作为学习笔记的积累&#xff0c;希望对来着有帮助。   绪论&#xff1a;笔者这里使用的是QTCreator和Python来实现一个简单的串口上位机的开发的简单过程&#…

软件测试复习02:静态测试

作者&#xff1a;非妃是公主 专栏&#xff1a;《软件测试》 个性签&#xff1a;顺境不惰&#xff0c;逆境不馁&#xff0c;以心制境&#xff0c;万事可成。——曾国藩 文章目录评审评审过程角色和职责评审类型静态分析控制流分析数据流分析编码标准一致性检查桌面检查代码走查…

Unity 之 资源加载 -- 可寻址系统面板介绍 -- 入门(二)

可寻址系统面板介绍 -- 入门&#xff08;二&#xff09;一&#xff0c;可寻址系统目录介绍1.2 创建分组1.2 目录介绍二&#xff0c;可寻址系统设置介绍2.1 Profile - 配置文件2.2 Catalog - 目录2.3 Content Update - 内容更新2.4 Downloads - 下载2.5 Build - 构建2.6 Build a…

69. 单发多框检测(SSD)代码实现以及QA

之前&#xff0c;我们分别介绍了边界框、锚框、多尺度目标检测和用于目标检测的数据集。 现在我们已经准备好使用这样的背景知识来设计一个目标检测模型&#xff1a;单发多框检测&#xff08;SSD&#xff09; 。该模型简单、快速且被广泛使用。尽管这只是其中一种目标检测模型&…

Filebeat从入门到实战

文章目录Filebeat的概念简介Filebeat特点Filebeat与Logstash对比Filebeat安装安装地址Logstash部署安装Filebeat实战对接LogstashFilebeat模块使用&#xff08;配置Kafka&#xff09;对接ES案例展示对接Kafka案例展示总结Filebeat的概念 简介 Filebeat是一种轻量型日志采集器…

【GP学习笔记三】锁与死锁

锁 一、概述 在GP中&#xff0c;定义了三种锁 自旋锁&#xff08;Spinlocks&#xff09;轻量级锁&#xff08;LWLocks&#xff09;普通锁&#xff08;Regular locks&#xff0c;也叫重量级锁&#xff09; 自旋锁 与互斥锁有点类似。针对某一项资源&#xff0c;在任何时刻&…