【C/C++】动态内存管理(C:malloc,realloc,calloc,free || C++:new,delete)

news2025/1/15 6:36:41

在这里插入图片描述

🔥个人主页: Forcible Bug Maker
🔥专栏: C++ | | C语言

目录

  • 前言
  • C/C++内存分布
  • C语言中的动态内存管理:malloc/realloc/realloc/free
    • `malloc`
    • `realloc`
    • `calloc`
    • `free`
  • C++中的动态内存管理:new/delete
    • new和delete操作内置类型
    • new和delete操作自定义类型
    • operator new与operator delete函数
    • new和delete的实现原理
    • 定位new表达式(placement-new)
  • 结语

前言

本篇博客主要内容:C++和C语言的动态内存管理方式,机制以及两者之间的区别。

在学习C语言的过程中,也曾涉及过动态内存管理,我们可以使用mallocrealloccalloc等函数来动态管理堆中空间资源。而在C++中,有了新的动态内存管理方式,那就是newdelete关键字。忽然发现之前似乎并没有讲C语言的几个动态内存管理函数,所以标题是 【C/C++】动态内存管理 ,不过不止如此,本次还会介绍new,delete关键字的底层,并区分一下C和C++内存管理之间的不同。

C/C++内存分布

在开始讲解之前,想通过一道题引入今天的内容。

#include<iostream>
using namespace std;
int globalVar = 1;
stat/ic int staticGlobalVar = 1;
void Test()
{
	static int staticVar = 1;
	int localVar = 1;
	int num1[10] = { 1, 2, 3, 4 };
	char char2[] = "abcd";
	const char* pChar3 = "abcd";
	int* ptr1 = (int*)malloc(sizeof(int) * 4);
	int* ptr2 = (int*)calloc(4, sizeof(int));
	int* ptr3 = (int*)realloc(ptr2, sizeof(int) * 4);
	free(ptr1);
	free(ptr3);
}

数据段就是我们常说的静态区,代码段就是我们所说的常量区。而动态内存管理,主要管理的是堆区中的内存空间

选择题:
选项: A.栈 B.堆 C.数据段(静态区) D.代码段(常量区)
①g/lobalVar在哪里?②____ staticGlobalVar在哪里?___
③//staticVar在哪里?___ ④localVar在哪里?____
⑤num1 在哪里?____

  1. globalVal是全局变量,存储在数据段(静态区)
  2. staticGlobalVal是静态全局变量,同时是静态的,因此它同样存储在数据段(静态区)
  3. staticVar是静态局部变量,存储在数据段(静态区),其生命周期贯穿整个程序的执行。
  4. localVar是局部变量,存储在上。
  5. num1是局部变量,本质是数组指针(存储着数组首元素地址)存储在上。

选择题:
①char2在哪里?____ ②char2在哪里?____
③pChar3在哪里?___ _④
pChar3在哪里?_____
⑤ptr1在哪里?____ ⑥*ptr1在哪里?____

  1. char2num1性质是一样的,为局部变量,是数组首元素地址,存储在上。
  2. *char2是栈帧中直接开辟空间存储的数据,在上。
  3. pChar3是局部指针变量,存储在上。
  4. *pChar3指向的内容(为常量字符串"abcd")存储在代码段(常量区)
  5. ptr1是局部指针变量,存储在栈上。
  6. *ptr1指向的内存空间是通过malloc动态开辟的,存储在上。
  • *char2(局部字符数组)
    当声明一个局部字符数组并用一个字符串字面量初始化的时候,如char char2[] = "abcd";char char2[5] = "abcd";时,编译器在栈上会为数组分配内存,然后将字符串字面量的内容(包括结尾的**\0**)复制到这块内存中。因此char2指向的内容存储在栈上。
  • *pChar(字符串字面量指针)
    当你使用指针去指向一个字符串常量(“abcd”)时,由于字符串常量是存储在代码段(常量区) 的,所以必须用const修饰才能接收到常量内容的地址(这样规定的原因是为了防止你对常/量做出修改,此时的"abcd"就跟数字1,2,3等等常量的性质是一样的)。故const char* pChar3 = "abcd";中,尽管pChar是一个指针,存储在栈中,但其却指向的字符串却存储在常量区。

*char2不在常量区,因为char2是局部字符数组,其内容直接存储在栈上。
*pChar3在常量区,是因为它指向的是一个字符串字面量(“abcd”),字符串字面量存储在程序的常量区,这部分内存只能读,不能改动。

在这里插入图片描述

内存主要可以分为几个部分:栈(Stack)堆(Heap)数据段(Data Segment)代码段(Code Segment)。而我们的数据通常也存储在这些地方。

  1. 栈(Stack)
    自动变量(包括局部变量和函数参数)通常分配在栈上。当函数被调用时,它的参数和局部变量会在栈上分配空间。当函数返回时,这些空间会被自动释放。
    栈内存分配和释放由编译器自动处理,不需要程序员手动管理。
  2. 堆(Heap)
    通过malloc、calloc、realloc等函数分配的内存位于堆上。堆用于动态内存分配,程序员需要手动管理内存的分配和释放。
    堆上的内存可以在程序的运行期间随时分配和释放,适用于需要动态创建和销毁的对象。
  3. 静态存储区
    全局变量和静态变量(无论是在函数内部还是外部声明的静态变量)存储在全局/静态存储区。
    这些变量在程序的整个生命周期中都存在,不会被自动释放。它们的初始化发生在程序启动时,释放则发生在程序结束时。
  4. 常量区
    存储常量字符串和字面量的地方。这些常量在程序的生命周期内都是固定的,不会被修改。

C语言中的动态内存管理:malloc/realloc/realloc/free

C语言里,关于动态内存的管理,是依靠一套标准的库函数完成的,它们包括mallocrealloccallocfree。这些函数允许在程序中随时开辟,分配和调整中的内存,都统一放在头文件<stdlib.h>中。下面是关于这些函数的基本用法以及它们之间的区别:

malloc

  • 头文件: <stdlib.h>
  • 函数声明: void* malloc(size_t size);
  • 功能: 在堆中开辟指定字节数的未初始化内存,并返回一个指向新开辟内存的指针。如果分配失败,则返回空指针NULL
  • 示例:
// 为代码开辟了大小能存放四个整型数据的空间
int* ptr = (int*)malloc(sizeof(int) * 4);
// 这个ptr指针,指向内存空间首元素地址
*ptr = 1;
*(ptr + 1) = 2;
*(ptr + 2) = 3;
*(ptr + 3) = 4;
for (int i = 0; i < 4; i++)
	printf("%d ", *(ptr + i));
printf("\n");

在这里插入图片描述

realloc

  • 头文件: <stdlib.h>
  • 函数声明: void* realloc(void* ptr,size_t size);
  • 功能: 调整之前调用malloc或calloc分配的内存块(传入的ptr为针指向此内存块的指针,如果ptr为NULL,那么realloc的功能就等同于malloc)。如果新的大小大于原始大小,可能会移动内存块到新的位置以提供足够的空间(移动过程也会把内存块中的值相应的拷贝到新的空间)。
  • 示例:
// 为代码开辟了大小能存放四个整型数据的空间
int* ptr = (int*)malloc(sizeof(int) * 4);
// 这个ptr指针,指向内存空间首元素地址
*ptr = 1;
*(ptr + 1) = 2;
*(ptr + 2) = 3;
*(ptr + 3) = 4;
//此时空间已经被放满
ptr = (int*)realloc(ptr, sizeof(int) * 5);
*(ptr + 4) = 5;
for (int i = 0; i < 5; i++)
	printf("%d ", *(ptr + i));
printf("\n");

在这里插入图片描述
在上面的示例代码中,使用realloc的方式是极其不安全且不被推荐的,当realloc开辟空间失败时,返回值NULL会让原本ptr指向的空间也丢失掉,所以使用realloc时,应该像下面这样。

int* ptr = (int*)malloc(sizeof(int) * 4);
int* tmp = (int*)realloc(ptr, sizeof(int) * 10);
// 判断是否realloc成功
if (tmp == NULL) {
	perror("realloc fail:");
	exit(1);
}
// 此时将tmp赋值给ptr就是安全的
ptr = tmp;

calloc

  • 头文件: <stdlib.h>
  • 函数声明: void* calloc(size_t num,size_t size);
  • 功能: 为指定数量的元素分配内存每个元素的大小在第二个参数中指定,并自动初始化所有位为0。如果分配失败,返回NULL
  • 示例:
// 为代码开辟了大小能存放四个整型数据的空间
// 同时初始化所有位为0
int* ptr = (int*)calloc(4, sizeof(int));
for (int i = 0; i < 4; i++)
	printf("%d ", *(ptr + i));
printf("\n");
// 这个ptr指针,指向内存空间首元素地址,
*ptr = 1;
*(ptr + 1) = 2;
*(ptr + 2) = 3;
*(ptr + 3) = 4;
for (int i = 0; i < 4; i++)
	printf("%d ", *(ptr + i));
printf("\n");

在这里插入图片描述

free

  • 头文件: <stdlib.h>
  • 函数声明: void free(void ptr);
  • 功能: 释放之前通过malloccallocrealloc分配的内存。一但内存被释放,被释放那块内存就不能再被访问了。
  • 示例:
int* ptr1 = (int*)malloc(sizeof(int) * 4);

int* ptr2 = (int*)malloc(sizeof(int) * 4);
int* ptr2 = (int*)realloc(ptr2, sizeof(int) * 10);

int* ptr3 = (int*)calloc(4, sizeof(int));

free(ptr1);
free(ptr2);
free(ptr3);

注:
在你开辟使用完堆中内存但忘记free释放时,编译器不会报错,但是被开辟的这块空间会一直存在于堆中,无法再次被开辟使用,导致内存泄露。内存泄露在大型项目中是个严重的暗病,不会立即显示,但是非常可能会在项目运行时冷不丁让空间开辟失败导致程序崩溃。
同时,不要尝试去释放未经分配的内存块或者多次释放同一个内存块,可能会导致未定义的行为,因此,每个分配的内存块至多free一次

C++中的动态内存管理:new/delete

C语言内存管理方式在C++中可以继续使用,但有些地方就无能为力,而且使用起来比较麻烦,因此C++又提出了自己的内存管理方式:通过newdelete操作符进行动态内存管理。

  • new:
    用于在运行时动态的分配内存并返回该内存的指针。它可以与数据类型一起使用,以指定要分配的内存大小和类型。例如,int* p = new int;这行代码会分配一个足以存储int类型数据的内存块,并将返回的地址赋值给指针p。
  • delete:
    用于释放由new分配的内存。在C++中,必须显示释放不再需要的内存,以防止内存泄漏。delete运算符接受一个指针作为参数,并释放该指针指向的内存。例如,delete p;这行代码会释放之前由new为p分配的内存。

接下来,我们详细讲讲new和delete的用法。

new和delete操作内置类型

在这里插入图片描述
申请和释放单个元素的空间,使用new和delete操作符,申请和释放连续的空间,使用new[]和delete[]。
下面可以来看一组代码案例:

// 动态申请一个int类型的空间
int* ptr1 = new int;
cout << *ptr1 << endl;

// 动态申请一个int类型的空间并初始化为10
int* ptr2 = new int(10);
cout << *ptr2 << endl;

// 动态申请10个int类型的空间
int* ptr3 = new int[3];
for (int i = 0; i < 3; i++)
	cout << *(ptr3 + i) << " ";
cout << endl;

// 动态申请10个int类型的空间,并初始化
int* ptr4 = new int[3] {1, 2};
for (int i = 0; i < 3; i++)
	cout << *(ptr4 + i) << " ";
cout << endl;

delete ptr1;
delete ptr2;
// 释放数组空间delete之后指针之前要加[]
delete[] ptr3;
delete[] ptr4;

以下是此段代码运行结果:
在这里插入图片描述
可以看出,单纯的new不会自动给内置类型初始化。所以,如果需要特定的值,需要像ptr2那样给动态申请的空间初始化
通过ptr3和ptr4的对比,会发现,new同样不会对动态开辟的数组进行初始化,但是可以通过ptr4初始化数组的方式,此时,未被赋值的类型会自动初始化成0

new和delete操作自定义类型

单纯拿new和delete对内置类型的操作来说,其实与C语言想必并没有什么太大的优势。但是C++中多了类这一个新的内容之后,new和delete就大有用武之地了。在申请自定义类型的空间时,new会调用构造函数,delete会调用析构函数,而malloc与free不会。 自动调用构造和析构的作用可不小,当你的自定义类型有一个指针指向某一块资源的时候,就非常有必要了。自动调用构造和析构可以帮助你在动态内存管理的过程中自动开辟和释放指对象中的针指向的资源,很大程度上避免了空指针和内存泄露等问题。
下面可以看一段代码案例帮助理解:

#include<iostream>
using namespace std;
class A
{
public:
	A(int a = 0)
		: _a(a)
	{
		cout << "A():" << this << endl;
	}
	~A()
	{
		cout << "~A():" << this << endl;
	}
private:
	int _a;
};
int main()
{
	// new/delete 和 malloc/free最大区别是 new/delete对于【自定义类型】
	// 除了开空间还会调用构造函数和析构函数
	A* p1 = (A*)malloc(sizeof(A));
	A* p2 = new A(1);
	free(p1);
	delete p2;
	cout << endl;
	
	// 内置类型是几乎是一样的
	int* p3 = (int*)malloc(sizeof(int)); // C
	int* p4 = new int;
	free(p3);
	delete p4;

	A* p5 = (A*)malloc(sizeof(A) * 10);
	A* p6 = new A[10];// 自动调用10次构造和析构
	free(p5);
	delete[] p6;
	cout << endl;
	return 0;
}

在这里插入图片描述

注:new和delete需要匹配使用,不要和C语言中的动态内存管理函数交叉,否则运行的结果是未定义的。

operator new与operator delete函数

newdelete是用户进行动态内存申请和释放的操作符operator newoperator delete是系统提供的全局函数new在底层调用operator new全局函数来申请空间,delete在底层通过operator delete全局函数来释放空间。

我们可以简单来看一下,operator new与operator delete的全局定义:

/*
operator new:该函数实际通过malloc来申请空间,当malloc申请空间成功时直接返回;申请空间
失败,尝试执行空 间不足应对措施,如果改应对措施用户设置了,则继续申请,否
则抛异常。
*/
void* __CRTDECL operator new(size_t size) _THROW1(_STD bad_alloc)
{
	// try to allocate size bytes
	void* p;
	while ((p = malloc(size)) == 0)
		if (_callnewh(size) == 0)
		{
			// report no memory
			// 如果申请内存失败了,这里会抛出bad_alloc 类型异常
			static const std::bad_alloc nomem;
			_RAISE(nomem);
		}
	return (p);
}

/*
operator delete: 该函数最终是通过free来释放空间的
*/
void operator delete(void* pUserData)
{
	_CrtMemBlockHeader* pHead;
	RTCCALLBACK(_RTC_Free_hook, (pUserData, 0));
	if (pUserData == NULL)
		return;
	_mlock(_HEAP_LOCK); /* block other threads */
	__TRY
		/* get a pointer to memory block header */
		pHead = pHdr(pUserData);
	/* verify block type */
	_ASSERTE(_BLOCK_TYPE_IS_VALID(pHead->nBlockUse));
	_free_dbg(pUserData, pHead->nBlockUse);
	__FINALLY
		_munlock(_HEAP_LOCK); /* release other threads */
	__END_TRY_FINALLY
		return;
}
/*
free的实现
*/
#define free(p) _free_dbg(p, _NORMAL_BLOCK)

通过上述两个全局函数的实现知道,operator new 实际也是通过malloc来申请空间,如果malloc申请空间成功就直接返回,否则执行用户提供的空间不足应对措施,如果用户提供该措施就继续申请,否则就抛异常operator delete 最终是通过free来释放空间的

new和delete的实现原理

本质上说,new实际上就是operator new的一个封装,而operator new又是malloc的一个封装;delete实际上就是operator delete的一个封装,而operator delete又是free的一个封装
在这里插入图片描述

  • 内置类型:
    如果申请的是内置类型的空间,new和malloc,delete和free基本类似,不同的地方是:new/delete申请和释放的是单个元素的空间,new[]和delete[]申请的是连续空间,而且new在申请空间失败时会抛异常,malloc会返回NULL。
  • 自定义类型:
    • new的原理
      1. 调用operator new函数申请空间
      2. 在申请的空间上执行构造函数,完成对象的构造
    • delete的原理
      1. 在空间上执行析构函数,完成对象中资源的清理工作
      2. 调用operator delete函数释放对象的空间
    • new T[N]的原理
      1. 调用operator new[]函数,在operator new[]中实际调用operator new函数完成N个对象空间的申请
      2. 在申请的空间上执行N次构造函数
    • delete[]的原理
      1. 在释放的对象空间上执行N次析构函数,完成N个对象中资源的清理
      2. 调用operator delete[]释放空间,实际在operator delete[]中调用operator delete来释放空间

定位new表达式(placement-new)

定位new表达式是在已分配的原始内存空间中调用构造函数初始化一个对象。

使用格式:
new (place_address) typenew(place_address)type(initializer-list)
place_address必须是一个指针,initializer-list是类型的初始化列表。

定位new表达式在实际中一般是配合内存池使用。因为内存池分配出的内存没有初始化,所以如果是自定义类型的对象,需要使用new的定义表达式进行显示调构造函数进行初始化。

下面看一组代码案例:

#include<iostream>
using namespace std;
class A
{
public:
	A(int a = 0)
		: _a(a)
	{
		cout << "A():" << this << endl;
	}
	~A()
	{
		cout << "~A():" << this << endl;
	}
	int _a;
};
// 定位new/replacement new使用演示
int main()
{
	// p1现在指向的只不过是与A对象相同大小的一段空间,还不能算是一个对象,因为构造函数没有执行
	A* p1 = (A*)malloc(sizeof(A));
	new(p1)A; // 注意:如果A类的构造函数有参数时,此处需要传参
	p1->~A();
	free(p1);
	cout << endl;
	
	A* p2 = (A*)operator new(sizeof(A));
	new(p2)A(10);
	p2->~A();
	operator delete(p2);
	cout << endl;

	// 当你想创建多个对象,可以考虑使用循环
	A* p3 = (A*)operator new(sizeof(A) * 4);
	for (int i = 0; i < 4; i++)
		new(p3 + i)A(10);

	for (int i = 0; i < 4; i++)
		cout << (p3 + i)->_a << " ";
	cout << endl;
	for (int i = 0; i < 4; i++)
		(p3 + i)->~A();
	cout << endl;

	// 要创建多个对象时,也可以这样使用定位new,编译器支持
	A* p4 = (A*)malloc(sizeof(A) * 4);
	new(p4)A[4] {1, 2, 3};
	for (int i = 0; i < 4; i++)
		cout << (p4 + i)->_a << " ";
	cout << endl;
	for (int i = 0; i < 4; i++)
		(p4 + i)->~A();
	free(p4);
	cout << endl;
	return 0;
}

运行结果如图:
在这里插入图片描述

结语

本篇博客详细讲解了C和C++中动态内存管理的方式,在C语言中,可以使用,malloc,realloc,calloc和free这四个函数进行动态内存管理;在C++中虽然也支持使用C中的四个函数,但新增的new和delete关键字能自动调用自定义类型的拷贝构造函数和析构函数,且开辟或释放失败后不再返回空指针,而是抛异常。我们同样讲到了operator new和operator delete这两个全局函数,它们通过封装能得到我们的new和delete。最后提到了定位new,可以支持给已经开辟的自定义类型空间进行构造或赋值。 关于内存管理的内容还不止于此,在后期的C++11的内容中,会讲到智能指针,内存泄露问题的规避管理等等知识。
博主后续还会产出更多有意思的内容,感谢大家的支持!♥

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

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

相关文章

android studio 编译一直显示Download maven-metadata.xml

今天打开之前的项目的时候遇到这个问题:android studio 编译一直显示Download maven-metadata.xml, AI 查询 报错问题&#xff1a;"android studio 编译一直显示Download maven-metadata.xml" 解释&#xff1a; 这个错误通常表示Android Studio在尝试从Maven仓库…

用Python Turtle画一个中国结

中国结&#xff0c;作为中华民族传统文化的象征之一&#xff0c;以其独特的编织技艺和深厚的文化内涵&#xff0c;深受人们喜爱。今天&#xff0c;我们就来用Python的turtle模块&#xff0c;尝试绘制一个充满韵味的中国结。 我们先来看看整个中国结生成的过程&#xff1a; 中国…

机器学习 | 准确率、召回率、精准率、特异度傻傻分不清?ROC曲线怎么看?一篇文章帮你搞定

一、真正类、假负类、假正类与真负类 二、准确率、召回率、精准率、特异度与假正率 1. 准确率 (Accuracy) 准确率表明成功预测&#xff08;预测为负或为正&#xff09;的结果占总样本的百分比。 准确率 &#xff0c; 2. 召回率/查全率/灵敏度/真正率&#xff08;Recall&a…

C语言进阶|双链表

✈链表的分类 链表的结构非常多样&#xff0c;以下情况组合起来就有8种&#xff08;2x22&#xff09;链表结构: 虽然有这么多的链表的结构&#xff0c;但是我们实际中最常用还是两种结构&#xff1a;单链表和双向带头循环链表 1.无头单向非循环链表&#xff1a;结构简单&…

springboot基于SpringBoot的网上订餐系统开题报告+1w字文档+ppt

项目演示视频: 【源码免费送】基于SpringBoot的网上订餐系统录像 摘 要 随着我国经济的飞速发展&#xff0c;人们的生活速度明显加快&#xff0c;在餐厅吃饭排队的情况到处可见&#xff0c;近年来由于新兴IT行业的空前发展&#xff0c;它与传统餐饮行业也进行了新旧的结合&…

实验八智能手机互联网程序设计(微信程序方向)实验报告

请在上一次实验的基础之上完成“手机快速注册”页面、“企业用户注册”页面&#xff0c;并实现点击手机快速注册和企业用户注册后转跳至该页面在“手机快速注册”页面&#xff0c;输入框内输入内容并失去焦点后&#xff0c;下方的按钮会变化 在企业用户注册页面&#xff0c;用户…

Anomalib:用于异常检测的深度学习库!

大家好,今天给大家介绍了一个用于无监督异常检测和定位的新型库:anomalib,Github链接:https://github.com/openvinotoolkit/anomalib 简介 考虑到可重复性和模块化,这个开源库提供了文献中的算法和一组工具,以通过即插即用的方法设计自定义异常检测算法。 Anomalib 包…

# 从浅入深 学习 SpringCloud 微服务架构(七)Hystrix(1)

从浅入深 学习 SpringCloud 微服务架构&#xff08;七&#xff09;Hystrix&#xff08;1&#xff09; 一、Hystrix&#xff1a;基于 RestTemplate 的熔断配置 1、Hystrix 介绍&#xff1a; 1&#xff09;Hystrix 是由 Netflix 开源的一个延迟和容错库&#xff0c; 用于隔离访…

Web3的可持续性:构建环境友好的去中心化系统

引言 随着全球对可持续发展和环境问题的日益关注&#xff0c;Web3技术作为一种新型的互联网模式&#xff0c;也开始受到社区和开发者的关注。但很少有人关注到Web3对环境可持续性的潜在影响。本文将探讨Web3如何构建一个环境友好的去中心化系统&#xff0c;以及这如何促进一个…

Shopee怎么选品成功率高达80%?请学

电商圈内流传着一句话&#xff1a;三分靠运营&#xff0c;七分靠选品。 选品在电商项目中至关重要&#xff0c;也是一个非常考验技巧和经验的环节。选品选择得好&#xff0c;后续的每一步都会变得相对轻松。 那么要怎么在众多商品中脱颖而出&#xff0c;提高在Shopee平台上选…

第三节课,功能2:开发后端用户的管理接口5min(用户的查询/状态更改)【4】【9开始--本人】

一、代码任务 【录个屏】 二、写代码 2.1 代码文件位置 2.2 代码如下&#xff1a; 2.3 官方文档&#xff1a; 网址&#xff1a; 逻辑删除 | MyBatis-Plus (baomidou.com) 三、代码有bug&#xff0c;没有鉴权&#xff0c;表里添加一个字段。role 管理员 3.1 判断操作的人&am…

了解 Postman:这个 API 工具的功能和用途是什么?

在软件开发中&#xff0c;经常听到 Postman 这个软件名。但其实很多新手开发者只知道这是软件开发常用的软件&#xff0c;并不知道实际是一个什么样工具&#xff0c;不知道具体的作用是什么。那今天就跟大家好好唠唠 Postman 这个软件。想要学习更多关于 Postman 的知识&#x…

call、apply、bind能用来干点啥(接上文)

上文我们了解了call、apply、bind的使用规则,学以致用,我们要在平时的搬砖中怎么使用呢? 其实好些人平时也用不到这三货,但是在框架底层,这三货可是经常被用到的啊,现在我们来了解了解吧 1、处理伪数组 假使,在html页面中有多个名为“c-container”的容器,现在我们来获取他…

[机缘参悟-166] :周期论:万物的周期现象是这个世界有序性和稳定性保障;超越周期:在轮回中,把握周期节奏。

目录 前言&#xff1a;超越周期 一、周期是大自然和宇宙的规律&#xff0c;是天道 1.1 概述 1.2 万物的周期规律的现象 1.3 电磁波的周期 二、计算机世界中的周期性 三、佛家的生命轮回规律 四、人类社会发展的周期规律 五、经济活动的周期规律 5.1 概述 5.2 股市的…

分享一个网站实现永久免费HTTPS访问的方法

免费SSL证书作为一种基础的网络安全工具&#xff0c;以其零成本的优势吸引了不少网站管理员的青睐。要实现免费HTTPS访问&#xff0c;您可以按照以下步骤操作&#xff1a; 一、 选择免费SSL证书提供商 选择一个提供免费SSL证书的服务商。如JoySSL&#xff0c;他们是国内为数不…

ArgoCD集成部署到Kubernetes

1&#xff1a;环境 kubernetes1.23.3ArgoCD2.3.3 2&#xff1a;ArgoCD介绍 Argo CD is a declarative, GitOps continuous delivery tool for Kubernetes. Argo CD是一个基于Kubernetes的声明式的GitOps工具。 那么&#xff0c;什么是GitOps呢&#xff1f; GitOps是以Git为基…

ROS 2边学边练(36)-- 添加一个坐标系(C++)

前言 此篇将会在之前已存在的几个坐标系&#xff08;/world、/turtle1、/turtle2&#xff09;的基础上再增加一个坐标系&#xff0c;相对来说&#xff0c;难度不大&#xff0c;主要是理解一些概念(脑子里面有3D场景的想象)&#xff0c;比如一个小车机器人处在世界坐标系&#x…

春秋云镜 CVE-2023-50563

靶标介绍&#xff1a; SEMCMS是一套支持多种语言的外贸网站内容管理系统&#xff08;CMS&#xff09;。SEMCMS v4.8版本存在SQLI&#xff0c;该漏洞源于SEMCMS_Function.php 中的 AID 参数包含 SQL 注入 开启靶场&#xff1a; 开始实验&#xff1a; 1、使用后台扫描工具&…

QT学习之QtXlsx

背景&#xff1a; 本来我是想提取xml中的信息存在xlsx文件中的&#xff0c;网上很多说是使用QtXlsx&#xff1b; 于是我找了一些帖&#xff0c; 像&#xff1a;https://www.cnblogs.com/liming19680104/p/14398459.html&#xff1b; 大家的说法都是安装第三方库到QT中&#xff…

社交媒体数据恢复:Skype国内、际版

恢复已删除的Skype聊天记录可能需要一些操作&#xff0c;但请注意&#xff0c;这不一定总是可行的&#xff0c;并且可能需要一些技术知识。以下是一些步骤&#xff0c;您可以尝试恢复您的Skype聊天记录&#xff1a; 1. 检查备份&#xff1a; - 如果您有Skype备份&#xff0…