当前位置: 首页 > news >正文

动态内存管理+动态通讯录【C进阶】

文章目录

  • 为什么存在动态内存分配❓
  • 👉动态内存函数👈
    • malloc&free
    • calloc
    • realloc
  • ❌常见的动态内存错误❌
  • 练习题
  • 🫠C/C++程序的内存开辟
  • 🤔柔性数组
    • 柔性数组的特点
    • 柔性数组的优势
  • :star:动态通讯录:star:
    • 初始化
    • 添加
    • 销毁

为什么存在动态内存分配❓

静态内存分配
当你声明数组时,你必须用一个编译时常量指定数组的长度(c99前)。但是,数组的长度常常在运行时才知道,这是由于它所需要的内存空间取决于输入数据。例如,一个用于计算学生等级和平均分的程序可能需要存储一个班级所有学生的数据,但不同班级的学生数量可能不同。在这些情况下,我们通常采取的方法是声明一个较大的数组,它可以容纳可能出现的最多元素。

这样声明的数组有3个缺陷

  • 这种声明引入了认为的限制,如果使用的长度超过了声明的长度,计算机无法处理这种情况
  • 如果程序使用的元素较少时,这样会导致多余的空间被浪费
  • 如果输入的数据超过了数组的容纳范围,那么程序不得不做出一种合理的相应
int main()
{int val = 20;//在栈上开辟4个字节int arr[10] = { 0 };//在栈上开辟40个字节的连续空间return 0;
}

上述开辟空间的方式有2个特点

  1. 开辟空间的大小是固定的
  2. 数组在声明时,必须指定数组的长度,它所需要的内存在编译时分配

上述开辟空间的方式称为静态内存开辟

动态内存分配
在计算机科学中, 动态内存分配(Dynamic memory allocation)又称为堆内存分配,是指计算机程序在运行期中分配使用内存。它可以当成是一种分配有限内存资源所有权的方法。
动态分配的内存在被程序员明确释放或被垃圾回收之前一直有效。与静态内存分配的区别在于没有一个固定的生存期。这样被分配的对象称之为有一个“动态生存期”。

👉动态内存函数👈

以下动态内存函数均包含头文件stdlib.h
动态内存函数开辟的空间都在堆上

malloc&free

在这里插入图片描述
malloc的参数是开辟空间的字节数

  • 如果开辟成功,则返回一个指向开辟好空间的指针开辟的内存存放的是随机值。
  • 如果开辟失败,则返回一个NULL指针,因此malloc的返回值一定要做检查
  • 返回值的类型是 void* ,所以malloc函数并不知道开辟空间的类型,具体在使用的时候使用者自己来决定。
  • 如果参数 size 为0,malloc的行为是标准是未定义的,取决于编译器。

在这里插入图片描述

  • free函数用来释放通过malloc,calloc,realloc动态开辟的空间
  • 如果指针ptr指向的空间不是上述函数动态开辟出来的,那么行为是未定义的
  • 如果ptr是NULL指针,那么调用free函数什么也不会做
int main()
{int i, n;char* buffer;printf("How long do you want the string? ");scanf("%d", &i);buffer = (char*)malloc(i + 1);//需要留一个空间给结束符if (buffer == NULL) exit(1);  //分配空间失败for (n = 0; n < i; n++) buffer[n] = rand() % 26 + 'a';buffer[i] = '\0';printf("Random string: %s\n", buffer);free(buffer);//释放动态开辟的内存return 0;
}

calloc

在这里插入图片描述
calloc函数的第一个参数是要开辟的元素个数,第二个参数是每一个元素的字节数

  • calloc动态开辟一段内存,并且将申请的字节中每一个比特位初始化为0
  • 开辟成功返回开辟的这段空间起始地址
  • 开辟失败返回NULL指针
  • 如果第二个参数为0,返回的结果# 取决于特定的库(不一定返回NULL指针),这个返回的指针不能够被解引用
int main()
{int* pa = (int*)calloc(5, sizeof(int)); //申请5个连续存储int的空间并初始化为0if (pa!=NULL)for (int i = 0; i < 5; i++) printf("%d ", pa[i]);free(pa);//释放动态开辟的内存return 0;
}

realloc

在这里插入图片描述
realloc函数让动态内存管理更灵活,我们可以通过realloc对动态开辟的内存进行更改(扩大/缩小)
realloc函数的第一个参数是待扩容内存起始地址,第二个参数是扩容后的字节数

  • 如果扩容成功,返回扩容内存后的首地址(可能与之前的地址不一样)
  • 如果扩容失败,返回NULL指针
  • 如果第一个参数为NULL指针,则realloc行为和malloc行文一样
  • 如果size参数为0,
    对于c90/c++98,ptr指向的空间被free并且返回NULL指针
    对于c99/c++11,返回值取决于特定的库实现:它可能是空指针或其他不应被取消引用的位置。
  1. 当原空间后面有连续足够大的空间时,realloc返回原空间起始地址
  2. 当原空间后面没有足够大的空间时

在这里插入图片描述
对于情况一:直接返回已知空间的起始地址

对于情况二:

  1. realloc寻找可以存放下的空间
  2. 将原来的在已知空间中的数据拷贝到可用空间中
  3. free已知空间
  4. 返回目标空间的起始地址
int main()
{int input, n;int count = 0;int* numbers = NULL;int* more_numbers = NULL;do {printf("Enter an integer value (0 to end): ");scanf("%d", &input);count++;more_numbers = (int*)realloc(numbers, count * sizeof(int));//没输入一个数申请一个多空间if (more_numbers != NULL) {numbers = more_numbers;numbers[count - 1] = input;}else perror("realloc失败->\n");} while (input != 0);printf("Numbers entered: ");for (n = 0; n < count; n++) printf("%d ", numbers[n]);free(numbers);return 0;
}

从这个例子中可以很好的体现动态开辟的优势,即使我事先不知道用户要输入多少个数(甚至用户也不知道),我也可以将用户输入的数字记录下来

注意:调用realloc时最后用临时变量接受返回值,不然返回值如果为NULL时原来已知空间中的地址找不到了,因为原本记录那个地址的变量现在变成了NULL

❌常见的动态内存错误❌

对NULL指针解引用

//1.对空指针解引用
int main()
{int* p = (int*)malloc(INT_MAX);*p = 20;free(p);return 0;
}

在这里插入图片描述

malloc开辟失败返回空指针,没有检查是否开辟成功就直接解引用,有可能解引用空指针,程序崩溃

对动态开辟空间的越界访问

//2.对动态开辟的内存进行越界访问
int main()
{int* p = (int*)malloc(sizeof(int) * 5);assert(p);for (int i = 0; i <= 5; i++){p[i] = i + 1;}	return 0;

p指向的是5个int的空间,但是当i等于5时,程序访问了未定义的位置,这样会越界访问,越界访问有可能会时程序崩溃,有可能不会(不代表问题不严重)

对非动态开辟内存使用free释放

int main()
{int	a = 10;int* p = a;free(p);return 0;
}

在这里插入图片描述

使用free释放动态开辟内存的一部分

//4.使用free释放动态开辟内存的一部分
int main()
{int* p = (int*)malloc(sizeof(int) * 5);free(++p);return 0;
}

对用一块内存多次释放

//5.对同一块内存多次释放
int main()
{int* p = (int*)malloc(sizeof(int) * 5);free(p);//释放一次后p指向的空间不在是动态开辟的了free(p);//此时释放非动态开辟的内存报错return 0;
}

动态开辟的内存忘记释放(内存泄漏)

void test()
{int* p = (int*)malloc(100 * sizeof(int));
}
int main()
{while (1){test();}return 0;
}

在这里插入图片描述
当内存大量泄漏时,程序会吃掉大部分内存,这样操作系统没有过多的内存分配给其他应用,因此内存泄漏可能会导致操作系统崩溃

切记:动态开辟的内存一定要释放,并且保证正确释放
为了避免这种情况,我们应该保证自己申请的内存自己释放,自己不释放的应当写文档告诉别人来释放

练习题

//1.下面程序会打印什么?
void GetMemory(char* p)
{p = (char*)malloc(100);
}int main()
{char* str = NULL;GetMemory(str);strcpy(str, "hello world");printf(str);
}

在这里插入图片描述
可以通过函数返回开辟的地址和传二级指针修正程序

//修正1
char* GetMemory()
{char* tmp = (char*)malloc(100);return tmp == NULL ? NULL : tmp;
}int main()
{char* str = GetMemory();strcpy(str, "Hello world");printf(str);free(str);//释放动态分配的内存str = NULL;return 0;
}
//修正2
void GetMemory(char** pp)
{*pp = (char*)malloc(100);
}int main()
{char* str = NULL;GetMemory(&str);strcpy(str, "Hello world");printf(str);free(str);str = NULL;return 0;
}
//2.输出结果是什么?
char* GetMemory(void)
{char p[] = "hello world";return p;
}
void Test(void)
{char* str = NULL;str = GetMemory();printf(str);
}

在这里插入图片描述

//3.输出什么
void GetMemory(char** p, int num)
{*p = (char*)malloc(num);
}
int main()
{char* str = NULL;GetMemory(&str, 100);strcpy(str, "hello");printf(str);return 0;
}

在这里插入图片描述

//4.输出什么?
int main()
{char* str = (char*)malloc(100);strcpy(str, "hello");free(str);if (str != NULL){strcpy(str, "world");printf(str);}
}

在这里插入图片描述

🫠C/C++程序的内存开辟

在这里插入图片描述

看见这个图,相比就会大致了解C/C++的内存区域规划了吧😼😼😼hhh~

🤔柔性数组

想必不少人一开始听到这个词比较陌生,什么叫做柔性数组?变长数组我知道,数组的长度可以是变量嘛,柔性数组是什么鬼嘛😵‍💫
柔性数组和变长数组都是在C99中加上的
C99 中,结构中的最后一个元素允许是未知大小的数组,这就叫做『柔性数组』成员。

柔性数组的特点

1.柔性数组不占结构体的大小
在这里插入图片描述
2.柔性数组只能是结构体中最后一个成员并且结构体除柔性数组外至少有一个其他成员

//定义柔性数组的两种错误写法
struct flexible_array
{int arr[];
};struct flexible_array
{int arr[];int i;
};

3.包含柔性数组成员的结构用malloc()函数进行内存的动态分配,并且分配的内存应该大于结构的大小,以适应柔性数组的预期大小

//malloc分配结构的大小,分配的空间必须大于结构的大小
typedef struct flexible_array
{int i;int arr[];
}flexible_array;
int main()
{//给柔性数组分配10个int大小flexible_array* pa =(flexible_array*)malloc(sizeof(flexible_array) + sizeof(int) * 10);assert(pa);for (size_t i = 0; i < 10; i++)  pa->arr[i] = i;for (size_t i = 0; i < 10; i++) printf("%d ", pa->arr[i]);free(pa);return 0;
}

更改数组的大小

int main()
{flexible_array* pa =(flexible_array*)malloc(sizeof(flexible_array) + sizeof(int) * 10);//给柔性数组分配10个int大小assert(pa);for (size_t i = 0; i < 10; i++)  pa->arr[i] = i;for (size_t i = 0; i < 10; i++) printf("%d ", pa->arr[i]);puts("");//数组扩容成20个int大小flexible_array* tmp = (flexible_array*)realloc(pa, sizeof(flexible_array) + sizeof(int) * 20);assert(tmp);pa = tmp;for (size_t i = 10; i < 20; i++) pa->arr[i] = i;for (size_t i = 0; i < 20; i++) printf("%d ", pa->arr[i]);puts("");free(pa);return 0;
}

柔性数组的优势

上述代码可以写成

typedef struct flexible_array
{int i;int* arr;
}flexible_array;
int main()
{flexible_array* pa = (flexible_array*)malloc(sizeof(flexible_array)); pa->arr = (int*)malloc(sizeof(int) * 10);for (size_t i = 0; i < 10; i++) pa->arr[i] = i;for (size_t i = 0; i < 10; i++) printf("%d ", pa->arr[i]);puts("");//flexible_array* tmp = (flexible_array*)realloc(pa->arr, sizeof(int) * 20);assert(tmp);pa->arr = tmp;for (size_t i = 10; i < 20; i++) pa->arr[i] = i;for (size_t i = 0; i < 20; i++) printf("%d ", pa->arr[i]);puts("");//先释放arrfree(pa->arr);free(pa);return 0;
}

对比上述两种写法
在这里插入图片描述

  • 第一个好处是:方便内存释放
    如果我们的代码是在一个给别人用的函数中,你在里面做了二次内存分配,并把整个结构体返回给
    用户。用户调用free可以释放结构体,但是用户并不知道这个结构体内的成员也需要free,所以你不能指望用户来发现这个事。所以,如果我们把结构体的内存以及其成员要的内存一次性分配好了,并返回给用户一个结构体指针,用户做一次free就可以把所有的内存也给释放掉。
  • 第二个好处:这样有利于访问速度.
    连续的内存有益于提高访问速度(计算机在访问当前地址时会默认把当前地址相邻的数据加载到寄存器中),也有益于减少内存碎片(使用柔性数组只调用一次malloc,而指针写法调用了两次malloc)

⭐️动态通讯录⭐️

在了解动态内存函数之后,我们可以将之前的静态通讯录改进为动态通讯录,不会静态通讯录看这里静态通讯录
首先明确一点:静态通讯录是通过一个大小固定的数组来存放联系人的信息,而数组的大小每次都是固定的,所以通讯录的长度不能更改,动态通讯录就是通讯录的容量可以更改,这样的好处有:1. 存多少人的信息就开辟多少空间,不够了随时可以扩容,2. 动态开辟的空间是在堆上的,堆上的空间比栈上的大,所以存储的联系人也比静态通讯录存储的多
将数组换成指针变量即可实现动态通讯录并且需要增加变量capacity来存储当前通讯录的最大容量

动态通讯录只有在初始化、增加联系人、销毁时和静态通讯录不一样

初始化

//动态通讯录
typedef struct Contact
{PeoInfo* data;//data是一个指针,指向动态开辟的内存int sz;		 //当前联系人个数int capacity;//当前最大容量
}Contact;//动态通讯录初始化
void InitContact(Contact* con)
{con->data = NULL;con->capacity = FITST_NUM;//一开始的最大容量con->sz = 0;
}

添加

添加联系人之前需要检查一下当前最大容量是否满了,如果满了需要扩容

//检查容量是否满了
void CheckContact(Contact* con)
{if (con->capacity == con->sz || con->sz == 0){PeoInfo* pc =(PeoInfo*)realloc(con->data, MAGNIFICATION * sizeof(con->capacity));if (NULL == pc){perror("扩容失败\n");return;}con->capacity *= MAGNIFICATION;//容量扩成当前最大容量的两倍con->data = pc;printf("扩容成功!当前容量最大容量%d\n", con->capacity);}return;
}//动态通讯录添加 
void AddContact(Contact* con)
{CheckContact(con);printf("请输入你需要添加人的姓名:");scanf("%s", con->data[con->sz].name);printf("请输出你需要添加人的年龄:");scanf("%d", &(con->data[con->sz].age));printf("请输入你需要添加人的性别:");scanf("%s", con->data[con->sz].sex);printf("请输入你需要添加人的电话:");scanf("%s", con->data[con->sz].tele);printf("请输入你需要添加人的地址:");scanf("%s", con->data[con->sz].address);con->sz++;printf("添加成功!\n");
}

销毁

//动态通讯录销毁
void DestroyContact(Contact* con)
{printf("你确定要清空通讯录吗?(YES/NO)\n");char selection[MAX] = { 0 };scanf("%s", selection);fflush(stdin);if (strcmp(selection, "YES") != 0) return;free(con->data);printf("清空成功!\n");
}

相关文章:

动态内存管理+动态通讯录【C进阶】

文章目录为什么存在动态内存分配❓&#x1f449;动态内存函数&#x1f448;malloc&freecallocrealloc❌常见的动态内存错误❌练习题&#x1fae0;C/C程序的内存开辟&#x1f914;柔性数组柔性数组的特点柔性数组的优势:star:动态通讯录:star:初始化添加销毁为什么存在动态内…...

基于pytorch+Resnet101加GPT搭建AI玩王者荣耀

本源码模型主要用了SamLynnEvans Transformer 的源码的解码部分。以及pytorch自带的预训练模型"resnet101-5d3b4d8f.pth"本资源整理自网络&#xff0c;源地址&#xff1a;https://github.com/FengQuanLi/ResnetGPT注意运行本代码需要注意以下几点 注意&#xff01;&a…...

多线程控制讲解与代码实现

多线程控制 回顾一下线程的概念 线程是CPU调度的基本单位&#xff0c;进程是承担分配系统资源的基本单位。linux在设计上并没有给线程专门设计数据结构&#xff0c;而是直接复用PCB的数据结构。每个新线程&#xff08;task_struct{}中有个指针都指向虚拟内存mm_struct结构&am…...

清晰概括:进程与线程间的区别的联系

相关阅读&#xff1a; &#x1f517;通俗简介&#xff1a;操作系统之进程的管理与调度&#x1f517;如何使用 jconsole 查看Java进程中线程的详细信息&#xff1f; 目录 一、进程与线程 1、进程 2、线程 二、进程与线程之间的区别和联系 1、区别 2、联系 一、进程与线程 …...

自定义类型 (结构体)

文章目录&#x1f4ec;结构体的声明&#x1f50e;1.结构的基础知识&#x1f50e;2.结构的声明&#x1f50e;3.特殊的声明&#x1f50e;4.结构的自引用&#x1f50e;5.结构体变量的定义和初始化&#x1f50e;6.结构体内存对齐&#x1f50e;7.修改默认对齐数&#x1f50e;8.结构体…...

第14届蓝桥杯STEMA测评真题剖析-2023年3月12日Scratch编程初中级组

[导读]&#xff1a;超平老师的《Scratch蓝桥杯真题解析100讲》已经全部完成&#xff0c;后续会不定期解读蓝桥杯真题&#xff0c;这是Scratch蓝桥杯真题解析第113讲。 蓝桥杯选拔赛现已更名为STEMA&#xff0c;即STEM 能力测试&#xff0c;是蓝桥杯大赛组委会与美国普林斯顿多…...

程序员接私活一定要知道的事情,我走的弯路你们都别走了

文章目录前言一、程序员私活的种类1.兼职职位众包2.自由职业者驻场3.项目整包二、这3种私活可以接1.有熟人2.七分熟的项目3.需求明确的项目三、这3种私活不要接1.主动找上门的中介单2.一味强调项目简单好做3.外行人给你拉的项目四、接单的渠道1.线下渠道2.线上渠道3.比较靠谱的…...

十二届蓝桥杯省赛c++(下)

1、 拿到题目一定要读懂题意&#xff0c;不要看到这题目就上来模拟什么闰年&#xff0c;一月的天数啥的。这个题目问你当天的时间&#xff0c;就说明年月日跟你都没关系&#xff0c;直接无视就好了。 #include <iostream> #include <cstring> #include <algori…...

数据结构与算法——堆的基本存储

目录 一、概念及其介绍 二、适用说明 三、结构图示 四、Java 实例代码 五.堆和栈的区别 一、概念及其介绍 堆(Heap)是计算机科学中一类特殊的数据结构的统称。 堆通常是一个可以被看做一棵完全二叉树的数组对象。 堆满足下列性质&#xff1a; 堆中某个节点的值总是不大…...

来了来了 !!!K8s指令、yaml部署

文章目录k8s资源清单一、k8s资源指令1、基础操作2、命令手册二、资源清单1、required2、optional3、other4、资源清单格式5、常用命令三、部署实例1、nginx3、eureka部署k8s资源清单 一、k8s资源指令 1、基础操作 #创建且运行一个pod #deployment、rs、pod被自动创建 kubect…...

spring-cloud-feign实战笔记

feign 配置 针对单个feign接口进行配置feign:client:config:# feignName 注意这里与contextId一致&#xff0c;不能写成name&#xff08;FeignClientFactoryBean#configureFeign&#xff09;# 不能写成 client-b (微服务名称)&#xff0c;否则不生效helloFeignClient: # conte…...

【Pytorch】利用PyTorch实现图像识别

本文参加新星计划人工智能(Pytorch)赛道&#xff1a;https://bbs.csdn.net/topics/613989052 这是目录使用torchvision库的datasets类加载常用的数据集或自定义数据集使用torchvision库进行数据增强和变换&#xff0c;自定义自己的图像分类数据集并使用torchvision库加载它们使…...

在家查找下载最新《柳叶刀》The Lancet期刊文献的方法

《柳叶刀》The Lancet简介&#xff1a; 《柳叶刀》The Lancet是全球顶尖综合性医学期刊&#xff0c;每周都会发表来自世界各地顶尖科学家的研究精粹。是由托马斯威克利&#xff08;Thomas Wakley&#xff09;创办于1823年&#xff0c;由爱思唯尔&#xff08;Elsevier&#xff…...

当下的网络安全行业前景到底怎么样?还能否入行?

前言网络安全现在是朝阳行业&#xff0c;缺口是很大。不过网络安全行业就是需要技术很多的人达不到企业要求才导致人才缺口大常听到很多人不知道学习网络安全能做什么&#xff0c;发展前景好吗&#xff1f;今天我就在这里给大家介绍一下。网络安全作为目前比较火的朝阳行业&…...

SpringCloud:SpringAMQP介绍

Spring AMQP是基于RabbitMQ封装的一套模板&#xff0c;并且还利用SpringBoot对其实现了自动装配&#xff0c;使用起来非常方便。Spring AMQP官方地址 Spring AMQP提供了三个功能&#xff1a; 自动声明队列、交换机及其绑定关系基于注解的监听器模式&#xff0c;异步接收消息封…...

第十三届蓝桥杯省赛 python B组复盘

文章目录前言主要内容&#x1f99e;试题 A&#xff1a;排列字母思路代码&#x1f99e;试题 B&#xff1a;寻找整数思路代码&#x1f99e;试题 C&#xff1a;纸张尺寸思路代码&#x1f99e;试题 D&#xff1a;数位排序思路代码&#x1f99e;试题 E&#xff1a;蜂巢思路代码&…...

SQL注入之HTTP请求头注入

Ps&#xff1a; 先做实验&#xff0c;在有操作的基础上理解原理会更清晰更深入。 一、实验 sqli-lab 1. User-Agent注入 特点&#xff1a;登陆后返回用户的 User-Agent --> 服务器端可能记录用户User-Agent 输入不合法数据报错 payload: and updatexml(1,concat("~&…...

Metasploit详细教程

第一步&#xff1a;安装和启动Metasploit 您可以从Metasploit官方网站下载适用于您操作系统的Metasploit框架。安装Metasploit框架后&#xff0c;您可以使用以下命令来启动Metasploit&#xff1a; msfconsole该命令将启动Metasploit控制台。 第二步&#xff1a;查找目标设备…...

【ChatGPT】Notion AI 从注册到体验:如何免费使用

欢迎关注【youcans的GPT学习笔记】原创作品&#xff0c;火热更新中 【ChatGPT】Notion AI 从注册到体验1. Notion AI 介绍1.1 Notion AI 简介1.2 Notion AI 的核心能力1.3 Notion AI 与 ChatGPT 的比较2. Notion AI 国内用户注册2.1 PC 端用户注册2.2 移动端用户注册3. Notion …...

每个开发人员都需要掌握的10 个基本 SQL 命令

SQL 是一种非常常见但功能强大的工具&#xff0c;它可以帮助从任何数据库中提取、转换和加载数据。数据查询的本质在于SQL。随着公司和组织发现自己处理的数据量迅速增加&#xff0c;开发人员越来越需要有效地使用数据库来处理这些数据。所以想要暗恋数据领域&#xff0c;SQL是…...

Vue项目预渲染

前言 Ajax 技术的出现&#xff0c;让我们的 Web 应用能够在不刷新的状态下显示不同页面的内容&#xff0c;这就是单页应用。在一个单页应用中&#xff0c;往往只有一个 html 文件&#xff0c;然后根据访问的 url 来匹配对应的路由脚本&#xff0c;动态地渲染页面内容。单页应用…...

可别再用BeanUtils了(性能拉胯),试试这款转换神器

老铁们是不是经常为写一些实体转换的原始代码感到头疼&#xff0c;尤其是实体字段特别多的时候。有的人会说&#xff0c;我直接使用get/set方法。没错&#xff0c;get/set方法的确可以解决&#xff0c;而且也是性能较高的处理方法&#xff0c;但是大家有没有想过&#xff0c;要…...

Transformer 杂记

Transformer输入的是token,来自语言序列的启发。卷积神经网络&#xff08;CNN&#xff09;是如何进行物种分类的.它实际是直接对特征进行识别&#xff0c;也就是卷积神经网络最基本的作用&#xff1a;提取图像的特征。例如&#xff1a;卷积神经网络判断一只狗的时候&#xff0c…...

实现异步的8种方式

前言异步执行对于开发者来说并不陌生&#xff0c;在实际的开发过程中&#xff0c;很多场景多会使用到异步&#xff0c;相比同步执行&#xff0c;异步可以大大缩短请求链路耗时时间&#xff0c;比如&#xff1a;「发送短信、邮件、异步更新等」&#xff0c;这些都是典型的可以通…...

Github隐藏功能显示自己的README,个人化你的Github主页

Github隐藏功能&#xff1a;显示自己的README 你可能还不知道&#xff0c;GitHub 悄悄上线了一个全新的个人页功能&#xff0c;显示一个自定义的 README.MD 在个人首页。要激活此功能&#xff0c;需要新建一个与自己 ID 同名的 Repository&#xff0c;新 Repo 里的README.MD将…...

单片机 | 51单片机原理

【金善愚】 单片机应用原理篇 笔记整理 课程视频 &#xff1a;https://space.bilibili.com/483942191/channel/collectiondetail?sid51090 文章目录一、引脚分布介绍1.分类2.电源引脚3.时钟引脚(2根)4.控制引脚(4根)5.端口引脚(32根)二、存储器结构及空间分布介绍1.存储器的划…...

(只需五步)注册谷歌账号详细步骤,解决“此电话号码无法验证”问题

目录 第一步&#xff1a;打开google浏览器 第二步&#xff1a;设置语言为英语&#xff08;美国&#xff09; 第三步&#xff1a;点击重新启动&#xff0c;重启浏览器 第四步&#xff1a;开始注册 第五步&#xff0c;成功登录google账号&#xff01; 如果出现这样的原因&…...

ChatGPT使用介绍、ChatGPT+编程、相关组件和插件记录

文章目录介绍认识ChatGPT是通过英汉互译来实现中文回答的吗同一个问题&#xff0c;为什么中英文回答不同ChatGPT的使用对话组OpenAI APIAI智能绘图DALLE 2ChatGPT for Google插件ChatGPT编程编写代码代码错误修正与功能解读代码评审与优化推荐技术方案编写和优化SQL语句在代码编…...

linux系统中复制粘贴和头文件问题解决方案

各位开发者大家好&#xff0c;好久不见&#xff0c;为了更好的服务大家&#xff0c;将平常所见所闻&#xff0c;以及遇到的问题和解决办法进行记录和总结。大家在学习过程中&#xff0c;有任何问题欢迎交流学习&#xff01;&#xff01;&#xff01;。 第一&#xff1a;如何将w…...

Vue项目实战 —— 后台管理系统( pc端 ) —— Pro最终版本

前期回顾 开源项目 —— 原生JS实现斗地主游戏 ——代码极少、功能都有、直接粘贴即用_js斗地主_0.活在风浪里的博客-CSDN博客JS 实现 斗地主网页游戏https://blog.csdn.net/m0_57904695/article/details/128982118?spm1001.2014.3001.5501 通用版后台管理系统&#xff0c;如果…...

做动漫网站的素材/下载一个百度时事新闻

游戏规则:开局后系统后台随机生成四个0-9之间的数字,玩家每次输入四个数字,中间以空格隔开,如果玩家输入的数字中位置和数字全对,则显示4A,玩家获胜,如果只是数字正确但位置对,相应的用B表示,如果数字和位置都不对,则不显示任何,例如玩家输入了1234回车后显示的是1A2…...

网页设计与网站开发项目/品牌策划方案模板

给表达式添加运算符282.给表达式添加运算符题目描述思路&#xff1a;回溯回溯282.给表达式添加运算符 题目描述 给表达式添加运算符 思路&#xff1a;回溯 回溯 假定字符串num长度为n&#xff0c;为构建表达式&#xff0c;可以往num中间的n-1个空隙添加号、-号、*号或者不添…...

网页设计 网站建设 哪个好/谷歌浏览器下载安装2023最新版

将本地项目提交到码云的远程仓库(微信小程序项目也是一样的操作)实现步骤如下&#xff1a;1、在码云上创建一个项目(远程仓库)2.进去git控制台 , 使用cd 命令进去本地仓库(前提&#xff1a;安装好git)3、使用 git init 命令 &#xff0c;初始化一个git 本地仓库(项目),会在本地…...

网站怎么做才有百度权重/生成关键词的软件免费

根据条件实现禁用...

万宁建设局网站/什么是淘宝搜索关键词

一、课程定位具有高职特色的实用计算机英语网络立体化课程针对国家教育部提出的“重点针对应用型人才”的培养要求&#xff0c;在充分借鉴了当今国外和国内ESP教学的研究成果并结合本教学团队十余年的高职计算机英语教学实践&#xff0c;以培养高职计算机专业学生基于岗位的实际…...

北京网页设计电脑培训/厦门网站推广优化哪家好

基础的数据结构和算法我们基本上学完了&#xff0c;接下来几节&#xff0c;我会讲几种更加基本的算法。它们分别是贪心算法、分治算法、回溯算法、动态规划。更加确切地说&#xff0c;它们应该是算法思想&#xff0c;并不是具体的算法&#xff0c;常用来指导我们设计具体的算法…...