C++ 指针详解
目录
一、指针概述
指针的定义
指针的大小
指针的解引用
野指针
指针未初始化
指针越界访问
指针运算
二级指针
指针与数组
二、字符指针
三、指针数组
四、数组指针
函数指针
函数指针数组
指向函数指针数组的指针
回调函数
指针与数组
一维数组
字符数组
二维数组
一、指针概述
指针的定义
数据是存放在内存中的,每一个内存空间都会有一个像房间号一样的编号,比如某某五星级酒店3109号房间,只有获得了这个编号才能找到这个房间,这个编号就是地址。而指针就是用来存放这个地址的变量。总结来说:指针是一个变量,是用来存放内存地址的变量,我们通常称谓指针变量。
指针的大小
是由计算机的物理性质决定的,一般的计算机分为32位机和64位机,32位机就是由32根地址线组成,每一根地址线都会传递高电平(1)或者低电平(0)。那么32根地址线就会产生2^32次方个地址,所以64位机的地址以此类推。8bite = 1字节——32位机的地址就由4个字节存储,62位机的地址就由8个字节的地址存储。
指针类型:数据的存储方式有 char、short、int、long、long long、float、double、struct、void
因此对应反指针类型也就有:char*、short*、int*、long*、long long*、float*、double*、struct*、void*
int main()
{//什么类型数据的地址就得放到对应类型的指针变量中char ch = 'w';char* pc = &ch;int num = 10;int* p = #return 0;
}
指针的解引用
指针的类型决定了,对指针解引用的时候有多大的权限(能取到多大的字节数)。比如: char* 的指针解引用就只能访问一个字节,而 int* 的指针的解引用就能访问四个字节。
野指针
指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)
指针未初始化
int main()
{ //局部变量指针未初始化,默认为随机值int *p;//没有指向对应的地址空间,无法查找地址*p = 20;return 0;
}
指针越界访问
int main()
{int arr[10] = {0};int *p = arr;for(int i=0; i<=11; i++){//当指针指向的范围超出数组arr的范围时,p就是野指针*(p++) = i;}return 0;
}
指针指向的空间释放,在堆里开辟内存的空间,如果被回收就不能在使用,因此指针就不能再指向那块空间的地址。
指针运算
指针的类型决定 + - 整数,指针变量所偏移的空间大小
int main()
{float arr[5];//指针+-整数;指针的关系运算for (float *p = &arr[0]; vp < &arr[5];){//后置++,先给数组赋值在偏移四个字节*p++ = 0;}return 0;}
指针 - 指针
//模拟实现strlen
int my_strlen(char *s)
{char *p = s;while(*p != '\0' )p++;return p-s;//两个指针之间的空间个数
}
指针的关系运算,允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针比较,但是不允许与指向第一个元素之前的那个内存位置的指针进行比较。
#define N_VALUES 5
int main()
{float values[N_VALUES];float *vp;//不能让数组第一个元素的地址与数组第一个元素之前的地址进行比较for(vp = &values[N_VALUES-1]; vp >= &values[0];vp--){*vp = 0;}return 0;
}
二级指针
指针变量也是一个变量,每一个变量都会存放到内存中,也就会有地址。二级指针,就是用来存放一级指针变量地址的变量。因此,存放一级指针变量地址的指针为二级指针,存放二级指针变量地址的指针为三级指针,以此类推。
指针与数组
可见数组名和数组首元素的地址是相同的。 因为数组是一块连续的空间,所以可以用指针指向数组首元素的地址,通过指针的加减来访问数组的每一个空间。
arr可以理解为一个变量,即一个内存空间。
二、字符指针
将字符变量的地址放到字符指针中称为字符指针。一种比较特殊的字符指针指向的是常量池中字符串首字符的地址,常量池当中的字符串是不能修改的。而将字符串放到数组当中进行存储的值是可以修改的。
char a = ‘w’;char* pa = &a;char* p = "abcdef";
备注:const加在*前表示不能修改指针所指向空间的值,const加在*后表示不能修改指针的指向
字符串数组和常量字符串的区别:
int main()
{//用相同的常量字符串去初始化不同的数组的时候就会开辟出不同的内存块//str1,str2字符串数组存放的是对应字符的asc码值//值虽然相同但是他们是两个不同数组,开辟的地址也是不同的char str1[] = "hello bit.";char str2[] = "hello bit.";//字符指针str3,str4存放的是字符串常量池的字符,存放的都是字符'h'的地址const char* str3 = "hello bit.";const char* str4 = "hello bit.";if (str1 == str2)printf("str1 and str2 are same\n");elseprintf("str1 and str2 are not same\n");if (str3 == str4)printf("str3 and str4 are same\n");elseprintf("str3 and str4 are not same\n");return 0;
}
三、指针数组
整型数组 - 存放整型的数组
字符数组 - 存放字符的数组
指针数组 - 存放指针(地址)的数组
指针数组是存放指针的数组,每种类型的数据都可以创建数组,但是数组也可以是由指针组成。
存放字符指针的数组
参数pc是是一个二级指针,存储的是abcdef字符串的地址,每次挪1字节
存放数组首地址的指针数组
四、数组指针
字符指针——存放字符地址的指针——指向字符的指针 char*
整型指针——存放整型地址的指针——指向整型的指针 int*
浮点型的指针——存放浮点型地址的指针——指向浮点型的指针 float* double*
数组指针——存放数组地址的指针——指向数组的指针
数组名和&数组名的区别:
数组指针的使用,使用一:两种打印数组的方式
数组指针的使用,使用二:二维数组的使用
//正常的接受二维数组的参数
void print1(int arr[3][4], int r, int c)
{int i = 0;for (i = 0; i < r; i++){int j = 0;for (j = 0; j < c; j++){printf("%d ", arr[i][j]);}printf("\n");}
}//用数组指针来接受二维数组,表示的是数组的第几行
void print2(int(*p)[4], int r, int c)
{int i = 0;for (i = 0; i < r; i++){int j = 0;for (j = 0; j < c; j++){ //printf("%d ", (*(p + i))[j]);printf("%d ", p[i][j]);}printf("\n");}
}int main()
{int arr[3][4] = { {1,2,3,4}, {2,3,4,5} , {3,4,5,6} };print1(arr, 3, 4);printf("\n");//数组名arr,表示首元素的地址//但是二维数组的首元素是二维数组的第一行//所以这里传递的arr,其实相当于第一行的地址,是一维数组的地址//可以数组指针来接收print2(arr, 3, 4);return 0;
}
函数指针
函数指针的定义与使用
类型名 (*指针变量名)(函数参数) = &函数名(或者直接写函数名)
//函数指针
int Add(int x, int y)
{return x + y;
}int main()
{//pf 是一个存放函数地址的指针变量 - 函数指针int (*pf)(int, int) = &Add;//可以理解为&Add给pfint ret = (*pf)(2,3);//&函数名和函数名都是函数的地址int (*pf)(int, int) = Add;//int ret = Add(2, 3);int ret = pf(2, 3);printf("%d\n", ret);return 0;
}
函数名也可以理解为一个指针变量,指针变量就是一块内存,内存中记录一个地址;变量也是一块内存直接记录值。*a取a的值,&a取a的低地址,a标识一块内存。
函数指针数组
函数指针数组的定义
数组是一个存放相同类型数据的存储空间,前面有讲到指针数组,那要把函数的地址存到一个数组中,那这个数组就叫函数指针数组。
数据类型 ( * 数组名[数值] ) (函数参数);
如:int ( * parr1 [ 10 ])();
int * parr2 [ 10 ]();
函数指针数组的使用(转移表)
void menu()
{printf("*******************************\n");printf("****** 1. add 2. sub *****\n");printf("****** 3. mul 4. div *****\n");printf("****** 0. exit *****\n");printf("*******************************\n");
}int Add(int x, int y)
{return x + y;
}int Sub(int x, int y)
{return x - y;
}int Mul(int x, int y)
{return x * y;
}int Div(int x, int y)
{return x / y;
}//函数指针数组存放上述函数的地址
//转移表--->传一个数,通过这个数找到对应的数组下标来调用对应的函数
int (*pf[5])(int, int) = { NULL, Add, Sub, Mul, Div };int main()
{int input = 0;int x = 0;int y = 0;int ret = 0;do{menu();printf("请选择:>");scanf("%d", &input);if (input == 0){printf("退出计算器\n");break;}else if (input>=1 &&input<=4){printf("请输入两个操作数:>");scanf("%d %d", &x, &y);ret = pf[input](x, y);printf("%d\n", ret);}else{printf("选择错误\n");}} while (input);return 0;
}
指向函数指针数组的指针
指向函数指针数组的指针是一个 指针指向一个数组, 数组的元素都是 函数指针
void test(const char* str)
{printf("%s\n", str);
}
int main()
{//函数指针pfunvoid (*pfun)(const char*) = test;//函数指针的数组pfunArrvoid (*pfunArr[5])(const char* str);pfunArr[0] = test;//指向函数指针数组pfunArr的指针ppfunArrvoid (*(*ppfunArr)[5])(const char*) = &pfunArr;return 0;
}
回调函数
回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。
void menu()
{printf("*******************************\n");printf("****** 1. add 2. sub *****\n");printf("****** 3. mul 4. div *****\n");printf("****** 0. exit *****\n");printf("*******************************\n");
}int Add(int x, int y)
{return x + y;
}int Sub(int x, int y)
{return x - y;
}int Mul(int x, int y)
{return x * y;
}int Div(int x, int y)
{return x / y;
}void calc(int (*pf)(int, int))
{int x = 0;int y = 0;int ret = 0;printf("请输入两个操作数:>");scanf("%d %d", &x, &y);ret = pf(x, y);printf("%d\n", ret);
}int main()
{int input = 0;do {menu();printf("请选择:>");scanf("%d", &input);switch (input){case 1:calc(Add);break;case 2:calc(Sub);break;case 3:calc(Mul);break;case 4:calc(Div);break;case 0:printf("退出计算器\n");break;default:printf("选择错误\n");break;}} while (input);return 0;
}
指针与数组
一维数组
int main()
{//一维数组int a[] = { 1,2,3,4 };//4*4=16printf("%d\n", sizeof(a));//16printf("%d\n", sizeof(a + 0));//a+0 其实是数组第一个元素的地址,是地址就是4/8字节printf("%d\n", sizeof(*a));//*a是数组首元素,计算的是数组首元素的大小,单位是字节,4printf("%d\n", sizeof(a + 1));//a+1是第二个元素的地址,是地址大小就是4/8printf("%d\n", sizeof(a[1]));//a[1]是第二个元素,计算的是第二个元素的大小-4-单位是字节printf("%d\n", sizeof(&a));//&a是整个数组的地址,整个数组的地址也是地址,地址的大小就是4/8字节//&a---> 类型:int(*)[4]printf("%d\n", sizeof(*&a));//&a是数组的地址,*&a就是拿到了数组,*&a--> a,a就是数组名,sizeof(*&a)-->sizeof(a)//计算的是整个数组的大小,单位是字节-16printf("%d\n", sizeof(&a + 1));//&a是整个数组的地址,&a+1,跳过整个数组,指向数组后边的空间,是一个地址,大小是4/8字节printf("%d\n", sizeof(&a[0]));//&a[0]是首元素的地址,计算的是首元素地址的大小,4/8字节printf("%d\n", sizeof(&a[0] + 1));//&a[0] + 1是第二个元素的地址,地址的大小就是4/8字节return 0;
}
字符数组
int main()
{//字符数组char arr[] = { 'a','b','c','d','e','f' };//char*//char [6]printf("%d\n", strlen(arr));//随机值printf("%d\n", strlen(arr + 0));//随机值//printf("%d\n", strlen(*arr));//strlen('a')->strlen(97),非法访问-err//printf("%d\n", strlen(arr[1]));//'b'-98,和上面的代码类似,是非法访问 - errprintf("%d\n", strlen(&arr));//&arr虽然是数组的地址,但是也是从数组起始位置开始的,计算的还是随机值//char(*)[6]printf("%d\n", strlen(&arr + 1));//&arr是数组的地址,&arr+1是跳过整个数组的地址,求字符串长度也是随机值printf("%d\n", strlen(&arr[0] + 1));//&arr[0] + 1是第二个元素的地址,是'b'的地址,求字符串长度也是随机值printf("%d\n", sizeof(arr));//arr单独放在sizeof内部,计算的是整个数组的大小,单位是字节,6printf("%d\n", sizeof(arr + 0));//arr + 0是数组首元素的地址,4/8printf("%d\n", sizeof(*arr));//*arr是数组的首元素,计算的是首元素的大小-1字节printf("%d\n", sizeof(arr[1]));//arr[1]是第二个元素,大小1字节printf("%d\n", sizeof(&arr));//取出的数组的地址,数组的地址也是地址,是地址大小就是4/8printf("%d\n", sizeof(&arr + 1));//&arr+1是跳过整个,指向数组后边空间的地址,4/8printf("%d\n", sizeof(&arr[0] + 1));//&arr[0] + 1是数组第二个元素的地址,是地址4/8字节return 0;
}
int main()
{char arr[] = "abcdef";//数组是7个元素//[a b c d e f \0]printf("%d\n", strlen(arr));//6,arr是数组首元素的地址,strlen从首元素的地址开始统计\0之前出现的字符个数,是6printf("%d\n", strlen(arr + 0));//arr + 0是数组首元素的地址,同第一个,结果是6printf("%d\n", strlen(*arr));//*arr是'a',是97,传给strlen是一个非法的地址,造成非法访问printf("%d\n", strlen(arr[1]));//errprintf("%d\n", strlen(&arr));//6printf("%d\n", strlen(&arr + 1));//&arr + 1是跳过数组后的地址,统计字符串的长度是随机值printf("%d\n", strlen(&arr[0] + 1));//&arr[0]+1是b的地址,从第二个字符往后统计字符串的长度,大小是5printf("%d\n", sizeof(arr));//7 - 数组名单独放在sizeof内部,计算的是数组的总大小,单位是字节printf("%d\n", sizeof(arr + 0));//arr+0是首元素的地址,大小是4/8printf("%d\n", sizeof(*arr));//*arr是数组首元素,大小是1字节printf("%d\n", sizeof(arr[1]));//arr[1]是数组的第二个元素,大小是1字节printf("%d\n", sizeof(&arr));//&arr是数组的地址,数组的地址也是地址,是4/8字节printf("%d\n", sizeof(&arr + 1));//&arr + 1是跳过整个数组的地址,是4/8字节printf("%d\n", sizeof(&arr[0] + 1));//&arr[0] + 1是第二个元素的地址,是4/8字节return 0;
}
int main()
{const char* p = "abcdef";printf("%d\n", strlen(p));//6- 求字符串长度printf("%d\n", strlen(p + 1));//p + 1是b的地址,求字符串长度就是5printf("%d\n", strlen(*p));//err,*p是'a'printf("%d\n", strlen(p[0]));//err - 同上一个printf("%d\n", strlen(&p));//&p拿到的是p这个指针变量的起始地址,从这里开始求字符串长度完全是随机值printf("%d\n", strlen(&p + 1));//&p+1是跳过p变量的地址,从这里开始求字符串长度也是随机值printf("%d\n", strlen(&p[0] + 1));//&p[0] + 1是b的地址,从b的地址向后数字符串的长度是5printf("%d\n", sizeof(p));//p是指针变量,大小就是4/8字节printf("%d\n", sizeof(p + 1));//p + 1是b的地址,是地址,就是4/8个字节printf("%d\n", sizeof(*p));//*p是'a',sizeof(*p)计算的是字符的大小,是1字节printf("%d\n", sizeof(p[0]));//p[0]-->*(p+0) --> *p 就同上一个,1字节printf("%d\n", sizeof(&p));//&p是二级指针,是指针大小就是4/8printf("%d\n", sizeof(&p + 1)); //&p + 1是跳过p变量后的地址,4/8字节printf("%d\n", sizeof(&p[0] + 1));//p[0]就是‘a’,&p[0]就是a的地址,+1,就是b的地址,是地址就是4/8return 0;
}
二维数组
int main()
{//二维数组int a[3][4] = { 0 };//printf("%p\n", &a[0][0]);//printf("%p\n", a[0]+1);printf("%d\n", sizeof(a));//48 = 3*4*4printf("%d\n", sizeof(a[0][0]));//4printf("%d\n", sizeof(a[0]));//a[0]是第一行的数组名,数组名单独放在sizeof内部,计算的就是数组(第一行)的大小,16个字节printf("%d\n", sizeof(a[0] + 1));//a[0]作为第一行的数组名,没有单独放在sizeof内部,没有取地址,表示的就是数组首元素的地址//那就是a[0][0]的地址,a[0]+1就是第一行第二个元素的地址,是地址就是4/8个字节printf("%d\n", sizeof(*(a[0] + 1)));//*(a[0] + 1)是第一行第2个元素,计算的是元素的大小-4个字节printf("%d\n", sizeof(a + 1));//a是二维数组的数组名,数组名表示首元素的地址,就是第一行的地址,a+1就是第二行的地址//第二行的地址也是地址,是地址就是4/8 //a - int (*)[4]//a+1--> int(*)[4]printf("%d\n", sizeof(*(a + 1)));//a+1是第二行的地址,*(a+1)表示的就是第二行,*(a+1)--a[1] //16printf("%d\n", sizeof(&a[0] + 1));//&a[0]是第一行的地址,&a[0]+1是第二行的地址,地址的大小就是4/8printf("%d\n", sizeof(*(&a[0] + 1)));//*(&a[0] + 1) 是对第二行的地址解引用,得到的就是第二行,计算的就是第二行的大小printf("%d\n", sizeof(*a));//a表示首元素的地址,就是第一行的地址,*a就是第一行,计算的就是第一行的大小//*a -- *(a+0)--a[0]printf("%d\n", sizeof(a[3]));//16字节 int[4]//如果数组存在第四行,a[3]就是第四行的数组名,数组名单独放在sizeof内部,计算的是第四行的大小int a = 10;printf("%d\n", sizeof(int));return 0;
}
相关文章:
C++ 指针详解
目录 一、指针概述 指针的定义 指针的大小 指针的解引用 野指针 指针未初始化 指针越界访问 指针运算 二级指针 指针与数组 二、字符指针 三、指针数组 四、数组指针 函数指针 函数指针数组 指向函数指针数组的指针 回调函数 指针与数组 一维数组 字符数组…...
.locked、locked1勒索病毒的最新威胁:如何恢复您的数据?
导言: 网络安全问题变得愈加严峻。.locked、locked1勒索病毒是近期备受关注的一种恶意软件,给用户的数据带来了巨大威胁。本文将深入探讨.locked、locked1勒索病毒的特征,探讨如何有效恢复被其加密的数据,并提供一些建议…...
Apache Sqoop使用
1. Sqoop介绍 Apache Sqoop 是在 Hadoop 生态体系和 RDBMS 体系之间传送数据的一种工具。 Sqoop 工作机制是将导入或导出命令翻译成 mapreduce 程序来实现。在翻译出的 mapreduce 中主要是对 inputformat 和 outputformat 进行定制。 Hadoop 生态系统包括:HDFS、Hi…...
【UGUI】实现UGUI背包系统的六个主要交互功能
在这篇教程中,我们将详细介绍如何在Unity中实现一个背包系统的六个主要功能:添加物品、删除物品、查看物品信息、排序物品、搜索物品和使用物品。让我们开始吧! 一、添加物品 首先,我们需要创建一个方法来添加新的物品到背包中。…...
电压驻波比
电压驻波比 关于IF端口的电压驻波比 一个信号变频后,从中频端口输出,它的输出跟输入是互异的。这个电压柱波比反映了它输出的能量有多少可以真正的输送到后端连接的器件或者设备。...
Open3D 最小二乘拟合二维直线(直接求解法)
目录 一、算法原理二、代码实现三、结果展示本文由CSDN点云侠原创,原文链接。爬虫网站自重。 一、算法原理 平面直线的表达式为: y = k x + b...
面试题目总结(二)
1. IoC 和 AOP 的区别 控制反转(Ioc) 和面向切面编程(AOP) 是两个不同的概念,它们在软件设计中有着不同的应用和目的。 IoC 是一种基于对象组合的编程模式,通过将对象的创建、依赖关系和生命周期等管理权交给外部容器或框架来实现程序间的解耦。IoC 的…...
TrustZone概述
目录 一、概述 1.1 在开始之前 二、什么是TrustZone? 2.1 Armv8-M的TrustZone 2.2 Armv9-A Realm Management Ext...
[go 面试] Go Kit中读取原始HTTP请求体的方法
关注公众号【爱发白日梦的后端】分享技术干货、读书笔记、开源项目、实战经验、高效开发工具等,您的关注将是我的更新动力! 在Go Kit中,如果你想读取未序列化的HTTP请求体,可以使用标准的net/http包来实现。以下是一个示例,演示了如何完成这个任务: package mainimport …...
小程序如何刷新当前页面?
在小程序中,刷新当前页面通常有两种方法: 使用 wx.navigateBack 方法: wx.navigateBack({delta: 1 }) 这将返回上一页,并刷新页面。你可以通过调整 delta 参数来控制返回的页面数。例如,如果你想要返回到两页之前的页…...
ChatGPT使用路径:从新手到专家的指南
原文&精华文章&转载注明:ChatGPT与日本首相交流核废水事件-精准Prompt... hello,我是小索奇,有任何问题或者需要帮助的都可以在这里找到我或者留言哈 一、初识ChatGPT 什么是ChatGPT? ChatGPT是一种大型语言模型&…...
VsCode 调试 MySQL 源码
1. 启动 MySQL 2. 查看 MySQL 进程号 [root ~]# ps -ef | grep mysqld root 21479 1 0 Nov01 ? 00:00:00 /bin/sh /usr/local/mysql/bin/mysqld_safe --datadir/usr/local/mysql/data --pid-file/usr/local/mysql/data/mysqld.pid root 26622 21479 0 …...
Mysql中的正经行锁、间隙锁和临键锁
行锁、间隙锁和临键锁是数据库中的三种不同类型的锁,三者都属于行锁,第一个一般叫他正经的行锁(《Mysql是怎样运行的》一书中的说法)。 行锁(Row Lock):行锁是指对数据表中的某一行进行的锁定操…...
最强AI之风袭来,你爱了吗?
2017年,柯洁同阿尔法狗人机大战,AlphaGo以3比0大获全胜,一代英才泪洒当场...... 2019年,换脸哥视频“杨幂换朱茵”轰动全网,时至今日AI换脸仍热度只增不减; 2022年,ChatGPT一经发布便轰动全球&a…...
时间序列预测实战(二十三)进阶版LSTM多元和单元预测(课程设计毕业设计首选)
一、本文介绍 本篇文章给大家带来的是利用我个人编写的架构进行LSTM模型进行时间序列建模(专门为了时间序列领域新人编写的架构,简单且不同于市面上大家用GPT写的代码),包括结果可视化、支持单元预测、多元预测、模型拟合效果检测…...
Python之Appium 2自动化测试(Android篇)
一、环境搭建及准备工作 1、Appium 2 环境搭建 请参考另一篇文章: Windows系统搭建Appium 2 和 Appium Inspector 环境 2、安装 Appium-Python-Client,版本要求3.0及以上 pip install Appium-Python-ClientVersion: 3.1.03、手机连接电脑,并在dos窗口…...
chromium通信系统-ipcz系统(四)-ipcz-分层、和mojo的关系以及handle
在只有mojo的情况下, 进程间通信都是靠unix 域套接字来完成了,由于这种方式比较低效,并且不够灵活,后来引入了ipcz。 但是系统中基本上使用mojo做进程间通信,想要一步到位迁移到ipcz系统是比较困难的。 所以chrome团队…...
推荐一些研发人员经常用到的免费API接口
快递物流订阅与推送(含物流轨迹):【物流订阅与推送、H5物流轨迹、单号识别】支持单号的订阅与推送,订阅国内物流信息,当信息有变化时,推送到您的回调地址。地图轨迹支持在地图中展示包裹运输轨迹。包括顺丰…...
高薪资是跳出来的,好工作是面出来的~
听人劝、吃饱饭,奉劝各位小伙伴,不要订阅该文所属专栏。 如需要项目实战或者是体系化资源,文末名片加V! 作者:哈哥撩编程,工作十余年, 从事过全栈研发、产品经理等工作,目前在公司担任研发部门CTO。荣誉:2022年度博客之星Top4、2023年度超级个体得主、谷歌与亚马逊开发…...
记QListWidget中QPushButton QSS样式失效的“bug”
一、场景 有一个QListWidget的列表;里面存放了若干QListWidgetItem;每个QListWidgetItem与一个自定义类对象绑定——通过QListWidget的setItemWidget()实现。自定义对象继承于QWidget,且内含QPushButton。 二、bug描述 在该QListWidget的外…...
python提取通话记录中的时间信息
您需要安装适合中文的SpaCy模型。您可以通过运行 pip install spacypython -m spacy download zh_core_web_sm来安装和下载所需的模型。 import spacy# 加载中文模型 nlp spacy.load(zh_core_web_sm)# 示例电话记录文本 text """ Agent: 今天我们解决一下这…...
DSShop移动商城网店系统 反序列化RCE漏洞复现
0x01 产品简介 DSShop是长沙德尚网络科技有限公司推出的一款单店铺移动商城网店系统,能够帮助企业和个人快速构建手机移动商城,并减少二次开发带来的成本。 以其丰富的营销功能,精细化的用户运营,解决电商引流、推广难题,帮助企业打造生态级B2C盈利模式商业平台。完备的电商…...
docker搭建node环境开发服务器
docker搭建node环境开发服务器 本文章是我自己搭建node环境开发服务器的过程记录,不一定完全适用所有人。根据个人情况,按需取用。 命名项目路径 为了方便cd到项目路径,将项目路径重命名,方便输入。 vim /etc/profile # 修改p…...
传统制造业企业如何实现数字化转型?
传统制造企业的数字化转型涉及利用数字技术来提高效率、生产力和整体业务流程。以下是实现制造业数字化转型的关键步骤和策略: 1.当前流程的评估: 确定可以从数字化转型中受益的领域。这可能包括生产流程、供应链管理、库存控制和客户关系。 评估技术集…...
面试:说一下深拷贝,浅拷贝,引用拷贝吧;Object类中的clone是哪种呢?
目录 深拷贝、浅拷贝、引用拷贝Object类的clone()方法 深拷贝、浅拷贝、引用拷贝 ● 浅拷贝: 对基本数据类型进行值传递; 对引用类型,复制了一份引用类型的变量 里面存储的内存地址一样 指向的对象也一样。 ● 深拷贝:对基本数据…...
接口压测指南
接口压测指南 一、 为什么需要进行接口压测二 、接口压测的目标是什么三、 用什么工具进行接口压测四、 接口压测核心指标4.1 JMeter的报告模板4.2 ApiPost报告模板 五、 接口慢如何排查5.1 大体排查思路5.2 排查工具5.3 压测经验 一、 为什么需要进行接口压测 突然有一天领导…...
计算机辅助药物设计AIDD-小分子-蛋白质|分子生成|蛋白质配体相互作用预测
文章目录 计算机辅助药物设计AIDD【小分子专题】AIDD概述及药物综合数据库学习机器学习辅助药物设计图神经网络辅助药物设计自然语言处理辅助药物设计药物设计与分子生成 计算机辅助药物设计【蛋白质专题】蛋白质数据结构激酶-Kinase相似性学习基于序列的蛋白质属性预测基于结构…...
深度学习-yolo目标检测-机器学习-计算机视觉-python学习路线(呕心沥血出品-绝对精品-附资源链接)
学习路线 1. 计算机视觉基础知识 图像处理基础:了解图像的基本处理技术,如滤波、边缘检测、直方图等。数字图像处理:熟悉数字图像的表示、颜色模型、图像增强等基本概念。opencv课程链接:Python for Computer Vision with OpenCV and Deep Learning资料推荐: 书籍:《数字…...
ubuntu2204 防火墙ufw限制某ip对某端口的访问
公司内部有个ip为10.10.10.1的网关,每天定时端口扫描,然后扫描发送的数据包http server解析不了,日志里就会记录这个错误,有点烦, 用防火墙过滤一下 ubuntu的防火墙命令是 ufw, 跟ufo挺像的,也…...
常见代码优化案例记录
1. 使用StringBuilder优化字符串拼接: // 不优化的写法 String result ""; for (int i 0; i < 1000; i) {result i; }// 优化的写法 StringBuilder resultBuilder new StringBuilder(); for (int i 0; i < 1000; i) {resultBuilder.append(i)…...
创新的企业网站开发/网站创建的流程是什么
概述通常情况下,一个Tomcat站点由于可能出现单点故障及无法应付过多客户复杂多样的请求等问题,不能单独应用于生产环境下,所以需要一套更可靠的解决方案来完善web站点架构。 nginx是一款优秀的http服务器软件,它能够支持多达50000…...
专业科技网站建设/百度框架户开户渠道
vi的使用--使用vi查找和替换 vi提供了几种定位查找一个指定的字符串在文件中位置的方法。同时还提供一种功能强大的全局替换功能。 1. 查找一个字符串 一个字符串是一行上的一个或几个字符。 为查找一个字符串,在vi命令模式下键入“/”,后面跟要查找的…...
郑州网站建设公司 艾特/移动建站模板
办公室是企业办公的地方,对于企业而言,一个办公室的形象对于企业在团队精神、宣传展示时十分关键,对于整体实力协作、客户信赖的展示也是有一定的影响。人们在对办公空间合理、利润较大化利用的同时,如何打造一个时尚的办公空间设…...
洛阳网站建设哪家权威/sem培训班学费哪个好
javascript是一种基于对象的语言,但它没有类的概念,所以又和实际面向对象的语言有区别,面向对象是javascript中的难点之一。现在就我所理解的总结一下,便于以后复习: 一、创建对象 1、创建自定义对象最简单的方式就是创…...
惠阳开发网站建设/全媒体广告投放平台
点击上方"蓝字"关注我们,享更多干货!索引分裂(Index Block Split),就是索引块的分裂。当一次DML操作修改了索引块上的数据,但是旧有的索引块没有足够的空间去容纳新修改的数据时,将分…...
江西建设职业技术学院迎新网站/关键的近义词
幂级数收敛 幂级数收敛求收敛半径一般是limn→∞an1anp,r1p\lim\limits_{n\to\infty}\frac{a_{n1}}{a_{n}}p,r\frac{1}{p}n→∞limanan1p,rp1或者开n次以后求极限。 但是对于抽象幂级数,可能先凑出一个半径,然后用幂级数性质说明 x1的时候…...