C++动态内存分配与指针

C 内存操作

malloc

C语言中动态分配内存指令:malloc

void* malloc(size_t size)

malloc将为用户分配size_t字节个内存,并且返回内存分配地址,如果分配失败,则返回0。

如:

1
2
3
4
// pa是分配好的内存首地址,4是分配的内存大小
int* pa = (int*) malloc(4);

// 如果分配失败则pa=0
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include<iostream>
int main()
{
	unsigned in;
	std::cin >> in;

	int* pa = (int*)malloc(in * sizeof(int));
	if (pa == nullptr)
	{
		std::cout << "内存分配失败" << std::endl;
	} 
	else
	{
		pa[0] = 12;
		pa[1] = 20;
		pa[2] = pa[0] * pa[1];

		std::cout << pa[0] << " " << pa[1] << " " << pa[2] << std::endl;
	}


	return 0;
}

calloc

void* calloc(size_t count, size_t size)

为用户分配count * size_t字节个内存,并返回内存分配的首地址,如果分配失败则返回0。

如:

1
int* pa = (int*) calloc(1, 4)

其中,pa是分配好的内存首地址,1是要分配的元素个数,4是要分配的每个元素的大小。

如果内存分配失败则返回0。

calloc命令会讲分配好的内存区域设置为0。

realloc

void* realloc(void* _block, size_t size);

为用户重新分配内存,_block是用户已经奉陪好的内存,size是要求重新分配的大小,函数返回重新分配后的内存首地址。

如果分配失败,那么返回0;

如:

1
2
int* pa = (int*)malloc(4);
     pa = (int*)realloc(pa, 4);
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include<iostream>
int main()
{
	unsigned in;
	std::cin >> in;

	int* pa = (int*)malloc(in * sizeof(int));
	int* copy_pa = pa;
	if (pa == nullptr)
	{
		std::cout << "内存分配失败" << std::endl;
	}
	else
	{
		pa[0] = 12;
		pa[1] = 20;
		pa[2] = pa[0] * pa[1];

		std::cout << pa[0] << " " << pa[1] << " " << pa[2] << std::endl;
	}

	std::cout << "请输入重新分配内存大小:";
	std::cin >> in;
	pa = (int*)realloc(pa, in);
	std::cout << "realloc之后内存中的值:" << pa[0] << " " << pa[1] << " " << pa[2] << std::endl;
	std::cout << "未重新分配前的pa地址:"<< copy_pa << "\nrealloc之后pa地址:"<< pa << std::endl;
	return 0;
}

/**
输出:
100
12 20 240
请输入重新分配内存大小:1000
realloc之后内存中的值:12 20 240
未重新分配前的pa地址:00E20A50
realloc之后pa地址:00E21C40
**/
  • realloc函数会保留内存中已有的值,只是内存地址重新分配了
  • 如果重新分配的内存小于原来的内存,那么首地址不变。
  • 如果重新分配的内存大于原来的内存,那么先判断扩大的内存中是否有已经被分配的,如果没有可以直接重新分配,如果已经有了,那么就需要重新找一段符合需求大小的内存段来重新分配。原内存中的值将会被拷贝过来。

free

void free(void* _block);

_block为需要释放的内存地址;

1
2
int* pa = (int*)malloc(4);
free(pa);

pa所占用的内存被释放

C++内存操作

分配

数据类型* 指针变量名称 = new 数据类型;

1
int* pa = new int;

数据类型* 指针变量名称 = new 数据类型[数量]

1
int* pa = new int[5];

分配失败pa返回0;

底层还是使用malloc来实现的。

释放

delete 指针

释放new分配的内存

delete[] 指针

释放new 数据类型[]分配的内存

悬挂指针

内存使用使用完毕之后,使用free或者delete释放之后,原指向该内存区域的指针就称之为悬挂指针,若此时再次使用该指针,可能就会出现问题。

不要使用已被释放的指针

不要重复释放内存

内存碎片

频繁的申请和释放小快内存会造成内存随便,虽然原则上还有内存可以使用,但是实际上由于剩余内存碎片化的存在,使得我们无法分配新的内存,当然,现在也不必担心这样的情况,因为new和delete背后的算法会尽力规避这个风险。

memcpy

void* memcpy(void* _dst, const void* _src, size_t size); memcpy可以将_src区域的内存复制到_dst区域,复制长度为_size

如:

1
2
3
int a[5]{1001, 1002, 1003, 1004};
int *p = new int[5];
memcpy(p, a, 5*sizeof(int));
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
#include<iostream>
int main()
{
	int a[5]{ 1001, 1002, 1003, 1004 };
	int* copy_a = new int[5];

	memcpy(copy_a, a, 5 * sizeof(int));
	for (int i = 0; i < 5; i++) std::cout << copy_a[i] << std::endl;

	return 0;
}

/**
输出:
1001
1002
1003
1004
0
**/

如果拷贝的空间大于_src的空间,则会将_src后面的的空间也拷贝到_dst,且会将_dst后面的空间覆盖掉。

memset

void* memset(void* _dst, int value, size_t _size)

value的值实际上是0~0xFF。

将指定内存区域的每一个自己的值都设置为val,_size

1
2
int* p = new int[100];
memset(p, 0, 100 * sizeof(int));
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include<iostream>
int main()
{
	int a[5]{ 1001, 1002, 1003, 1004 };
	int* copy_a = new int[5];

    // 尝试设置四个字节,实际上只接受了最低的两个字节(34)
	memset(a, 0x1234, 5 * 4);
	memcpy(copy_a, a, 5 * sizeof(int));
	for (int i = 0; i < 5; i++) std::cout << std::hex << copy_a[i] << std::endl;

	return 0;
}

/**
输出:
34343434
34343434
34343434
34343434
34343434
**/

指针的本质是一种特殊的变量类型

声明

1
2
3
4
5
int* a;
int *a;

// 多个指针变量定义不可以如下定义
int *a, b;

取址运算

1
2
int a = 200;
int* pA = &a;

间接运算符

1
2
// 将pA地址里的值设置为400
*pA = 400;

指针数组

指针也可以通过数组的方式声明

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
#include<iostream>
int main() {
	int a[5]{ 3,6,8,3,5 };
	int* pA[5]{};

	for (int i = 0; i < 5; i++)
	{
		pA[i] = &a[i];
		std::cout << "a[" << i << "] 的地址为:" << pA[i] << std::endl;
	}
	return 0;
}

打印内容:
a[0] 的地址为:001EF864
a[1] 的地址为:001EF868
a[2] 的地址为:001EF86C
a[3] 的地址为:001EF870
a[4] 的地址为:001EF874

指针大小

使用sizeof()方法来获得指针的大小

1
2
3
4
5
6
7
8
9
#include<iostream>
int main() {
	int		  a{ 111 };
	int* pA{ &a };
	std::cout << sizeof(pA) << std::endl;
}

打印结果:
4

指针类型转换

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
#include<iostream>
int main() {
	unsigned ua{ 222 };

	int* pA = (int*)&ua;
	*pA = -1;

	std::cout << pA << std::endl;
	std::cout << ua << std::endl;
	return 0;
}

输出:
004FF968
4294967295

场景

*ptr++

地址增加。指针加1= 该指针指向地址 + 1 * 改指针类型的大小

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
#include<iostream>
int main() 
{
	int a[]{10001, 20001, 30001, 40001};
	int* pA{ &a[0] };

	std::cout << "地址为:" << pA << ",值为:" << *pA << std::endl;
	std::cout <<*pA++<< std::endl;
	std::cout << "地址为:" <<pA << ",值为:" << *pA << std::endl;
	return 0;
}

输出:
地址为:0073FCC8,值为:10001
10001
地址为:0073FCCC,值为:20001

(*ptr)++

ptr指针指向地址中的值增加

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
#include<iostream>
int main()
{
	int a[]{ 10001, 20001, 30001, 40001 };
	int* pA{ &a[0] };

	std::cout << "地址为:" << pA << ",值为:" << *pA << std::endl;
	std::cout << (*pA)++ << std::endl;
	std::cout << "地址为:" << pA << ",值为:" << *pA << std::endl;
	return 0;
}

输出:
地址为:0077FB40,值为:10001
10001
地址为:0077FB40,值为:10002

指针的指针

指针变量也是一个变量,在内容空间中也有具体的地址

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
#include<iostream>
int main()
{
	int a[]{ 10001, 20001, 30001, 40001 };
	int* pA{ &a[0] };

	int** ppA{&pA};
	std::cout << "地址为:" << ppA << ",值为:" << *ppA << std::endl;
	std::cout << "地址为:" << *ppA << ",值为:" << **ppA << std::endl;
	return 0;
}

输出:
地址为:00EFF984,值为:00EFF990
地址为:00EFF990,值为:10001

修改指针的指向

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include<iostream>
int main()
{
	int a[]{ 10001, 20001, 30001, 40001 };
	int* pA{ &a[0] };

	int** ppA{ &pA };
	std::cout << "地址为:" << ppA << ",值为:" << *ppA << std::endl;
	std::cout << "地址为:" << *ppA << ",值为:" << **ppA << std::endl;
	std::cout << "地址为:" << pA << ",值为:" << *pA << std::endl;

    // *ppA 即 pA 
	*ppA = &a[1];
	std::cout << "地址为:" << ppA << ",值为:" << *ppA << std::endl;
	std::cout << "地址为:" << *ppA << ",值为:" << **ppA << std::endl;
	std::cout << "地址为:" << pA << ",值为:" << *pA << std::endl;
	return 0;
}


输出:
地址为:005CF82C,值为:005CF838
地址为:005CF838,值为:10001
地址为:005CF82C,值为:005CF83C
地址为:005CF83C,值为:20001

常量指针

定义:

const 变量类型*

所谓常量指针,即这个指针指向的是一个常量的地址,常量指针中,不能对其指向的内存地址进行改变,但是指针指向的这个地址可以改变

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
#include<iostream>
int main() 
{
	const int a{ 100 };
	const int b{ 2500 };
	int		  c{ 3000 };

	const int* ptr{ &a };
	ptr = &b;

	// 不能进行如下操作
	//*ptr = 500;

	ptr = &c;
	// 虽然c不是常量,但是依然不能进行如下操作,因为ptr是const修饰的
	//*ptr = 500;
}

指针常量

定义: 变量类型* const

所谓的指针常量,即这个指针变量是一个常量,一旦初始化就不可以再指向其他内存地址,但是内存地址中的数据可以读写

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
#include<iostream>
int main()
{
	int a{ 100 };
	int b{ 2500 };
	int c{ 3000 };

	int* const ptr{ &a };
	// 虽然指针的地址不可以改变,但是指针指向地址中的值可以改变
	*ptr = 500;

	// 不能进行如下操作
	// ptr = &b;
}

指向常量的常量指针

定义:

const 变量类型* const

指向常量的常量指针:即这个指针变量是一个常量,一旦初始化就不可以再指向其他内存地址,因为其本身就是一个指向常量的指针,所以其指向的内存区域也不可以修改。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
#include<iostream>
int main()
{
	int a{ 100 };
	int b{ 2500 };
	int c{ 3000 };

	const int* const ptr{ &a };
	// 不能进行 如下操作
	// *ptr = 500;

	// 也不能进行如下操作
	// ptr = &b;
}

可以通过如下方式修改

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
#include<iostream>
int main()
{
	const int a{ 1000 };
	const int b{ 2500 };
	const int c{ 3000 };

	const int* const ptr{ &a };
	// 不能进行 如下操作
	// *ptr = 500;

	// 也不能进行如下操作
	// ptr = &b;

	// 去掉a变量的const之后 *ptr 和 *ptrA的值都改变了
	int* ptrA{ (int*)&a };
	*ptrA = 9500;
	std::cout << "地址:" << &a << ",值为:" << a << std::endl;
	std::cout << "地址:" << ptrA << ",值为:" << *ptrA << std::endl;
	return 0;
}

指针和数组

相同

数组的底层实现是利用了指针

从原来上将,指针和数组是同一个方法的不同表达方式,而数组名本身就是一个指针,数组元素只是这个指针按照一定量偏移后对应的内存区域里的内容。

指针同样可以使用[]符号来操作内存

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
#include<iostream>
int main() 
{
	int a[]{ 1000, 2000, 3000 };
	int* ptrA{ a };

	a[0] = 1001;
	a[2] = 3003;

	// 指针同样可以使用[]符号来操作内存
	ptrA[1] = 2002;
	
	return 0;
}

对应的汇编代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
	;int a[]{ 1000, 2000, 3000 };
007F34E2  mov         dword ptr [a],3E8h  
007F34E9  mov         dword ptr [ebp-10h],7D0h  
007F34F0  mov         dword ptr [ebp-0Ch],0BB8h  
	;int* ptrA{ a };
007F34F7  lea         eax,[a]  
007F34FA  mov         dword ptr [ptrA],eax  

	;a[0] = 1001;
007F34FD  mov         eax,4  
007F3502  imul        ecx,eax,0  
007F3505  mov         dword ptr a[ecx],3E9h  
	;a[2] = 3003;
007F350D  mov         eax,4  
007F3512  shl         eax,1		; eax左移1位,等于将eax中的值(4)乘以2
007F3514  mov         dword ptr a[eax],0BBBh  

不同

在使用`size函数来获取数组大小的时候,返回是整个数组的大小

而指针返回的则是指针类型的大小。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
#include<iostream>
int main() 
{
	int a[]{ 1000, 2000, 3000 };
	int* ptrA{ a };

	a[0] = 1001;
	a[2] = 3003;

	// 指针同样可以使用[]符号来操作内存
	ptrA[1] = 2002;
	
	std::cout << "数组a大小" <<sizeof(a) << std::endl;
	std::cout << "指针ptrA的大小" <<sizeof(ptrA) << std::endl;

	return 0;
}

输出:
数组a大小12
指针ptrA的大小4

多维数组

数组的本质是连续的内存区域,所以所谓的多维数组其实是不存在的,多维只是方便理解而创造出来的逻辑方法。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
#include<iostream>
int main()
{
	int a[2][5]
	{
		{1001, 1002, 1003, 1004, 1005},
		{2001, 2002, 2003, 2004, 2005}
	};

	int b[2][6]
	{
		{0, 1001, 1002, 1003, 1004, 1005},
		{0, 2001, 2002, 2003, 2004, 2005}
	};

	int* pA{ a[0] };
	std::cout << a[1][4] << std::endl;
	// 因为是连续的内存空间
	std::cout << pA[9] << std::endl;
    return 0;
}

数组指针

注意和指针数组的区别

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include<iostream>
int main()
{
	int a[2][5]
	{
		{1001, 1002, 1003, 1004, 1005},
		{2001, 2002, 2003, 2004, 2005}
	};

	int b[2][6]
	{
		{0, 1001, 1002, 1003, 1004, 1005},
		{0, 2001, 2002, 2003, 2004, 2005}
	};


	// 指针数组
	//int* pArr[5];
	
	// 数组指针, 每一行中有5个数据,本质上是一个指针
	int(*pArr)[5]{a};
	// 声明了数组指针之后可以按照二维数组的形式获取地址中的数据
	std::cout << "数组指针:" << pArr[1][4] << std::endl;
	std::cout << "数组指针大小:" << sizeof(pArr) << std::endl;
	
	// 数组指针加1的时候,相当于维度*数据类型的大小,这里是6(维度)*4(int的大小)
	std::cout << "数组指针大小:" << pArr << std::endl;
	pArr = pArr + 1;
	std::cout << "偏移之后数组指针大小:" << pArr << std::endl;

	return 0;
}

输出:
数组指针:2005
数组指针大小:4
数组指针大小:006FF91C
偏移之后数组指针大小:006FF930

数组指针加1的时候,相当于维度*数据类型的大小

sizeof()

sizeof()方法在编译期就已经知道了大小。

堆栈

堆的本质是空闲内存,C++中把堆称之为自由存储区,只要是程序加载后没有占用的空闲内存,都是自由存储区域,使用new和malloc申请一块新的内存区域,都是由操作系统从对上操作的。

栈是程序在编译时就确定了大小的一段内存区域,主要是用于里临时变量的存储,栈的效率要高于堆,但是容量有限。


定义

引用是创建一个变量的引用名称

语法: 数据类型& 变量名称{引用对象名称}

如:

1
2
int a{500};
int& ra{a};

ra = 5200时,相当于a=5200

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
#include<iostream>
int main()
{
	int  a{ 1500 };
	int& ref_a{ a };
	std::cout << "a=" << a << " ref_a=" << ref_a << std::endl;

	ref_a = 2400;
	std::cout << "a=" << a << " ref_a=" << ref_a << std::endl;
	return 0;
}

输出:
/**
a=1500 ref_a=1500
a=2400 ref_a=2400
**/

引用一旦赋值就无法改变

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
#include<iostream>
int main()
{
	int  a{ 1500 };
	int	 b{ 2000 };
	int& ref_a{ a };
	std::cout << "a=" << a << " ref_a=" << ref_a << std::endl;

	ref_a = 2400;
	std::cout << "a=" << a << " ref_a=" << ref_a << std::endl;
	
	// 这里并不是将ref_a设置成了b的引用,而是将a的值修改成了b
	ref_a = b;

	return 0;
}

引用取址

同一个变量的引用指向同一个地址

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include<iostream>
int main()
{
	int  a{ 1500 };
	int	 b{ 2000 };
	int& ref_a{ a };
	int& ref_b{ a };
	int& ref_c{ a };
	int& ref_d{ a };
	std::cout << "a=" << a << " ref_a=" << ref_a << std::endl;

	ref_a = 2400;
	std::cout << "a=" << a << " ref_a=" << ref_a << "地址="<< &ref_a <<std::endl;
	std::cout << "a=" << a << " ref_b=" << ref_b << "地址="<< &ref_b << std::endl;
	std::cout << "a=" << a << " ref_c=" << ref_c << "地址=" << &ref_c << std::endl;
	std::cout << "a=" << a << " ref_d=" << ref_d << "地址=" << &ref_d <<std::endl;
	
	// 这里并不是将ref_a设置成了b的引用,而是将a的值修改成了b
	ref_a = b;

	return 0;
}

输出:
a=1500 ref_a=1500
a=2400 ref_a=2400 地址=0107F750
a=2400 ref_b=2400 地址=0107F750
a=2400 ref_c=2400 地址=0107F750
a=2400 ref_d=2400 地址=0107F750

常量引用

引用的值无法修改

const int& a{b}

则无法修改a的值。


定义

std::unique_ptr是所谓智能指针中的一种,主要目的是为了解决原生指针安全性不足的弊端

声明:

std::unique_ptr<类型> 变量名称{};

1
2
3
4
5
// 这里的150表示数组的size为150
std::unique<int> ptrA{std::make_unique<int>(150)};

// 这里的10表示初始化智能指针所指地址中的值初始化为10
std::unique<int> ptrA{std::make_unique<int[]>(10)};

常用方法:

reset()

reset()方法会释放掉std::unique_ptr的内存空间,并且将std::unique_ptr设置为nullptr;

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
#include<iostream>
int main()
{
	int* a = new int[5];
	// 这里的5表示数组的size为5
	std::unique_ptr<int[]> ptr_arr{ std::make_unique<int[]>(5) };
	// 这里的5表示初始化智能指针所指地址中的值初始化为5
	std::unique_ptr<int> ptr{ std::make_unique<int>(5) };

	std::cout << "地址为:" << ptr << "值为:" << *ptr << std::endl;

	ptr.reset();
	std::cout << "地址为:" << ptr << "值为:" << *ptr << std::endl;
	return 0;
}

get()

会返回一个std::unique_ptr的指针

用法:

1
2
std::unique_ptr<int> ptrA{std::make_unique<int>(150)};
int* p = ptrA.get();

get()等于ptrA申请内存时的地址。

release()

会返std::unique_ptr的指针,并将std::unique_ptr设置为nullptr,但是注意release并不会释放器占用的内存空间。

用法:

1
2
std::unique_ptr<int> ptrA{std::make_unique<int>(150)};
int *ptr = ptrA.release();

此时ptrA所占用的内存空间没有被释放,只是将ptrA的值设置成了nullptr

ptr等于ptrA申请内存时的地址。

std::move

std::unique_ptr指针具有唯一性,因此不能被复制,但是可以转移。

转移语法: 转以后的指针变量 = std::move(转移前的指针变量);

如:

1
2
3
4
std::unique_ptr<int> ptrA {std::make_unique<int>(150)};
std::unique_ptr<int> ptrB {};

ptrB = std::move(ptrA);

转移后ptrA被设置为nullptr

std::shared_ptr

可以有多个std::shared_ptr指向同一个地址,同一个地址下只有当最后一个std::shared_ptr释放的时候,才会释放其所占用的内存空间,std::shared_ptr会记录当前地址有多少个智能指针调用。

语法:

std::shared_ptr<类型> 变量名称

例如:

1
2
std::shared_ptr<int> ptrA{};
std::shared_ptr<int> ptrB {std::make_shared<int>(5)};

std::make_shared不支持数组

std::shared_ptr<int[]> ptrC{new int[5]{1,2,3,4,5}}

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
#include<iostream>
int main()
{
	int* a{};
	std::shared_ptr<int> ptrA{ new int{5} };
	std::shared_ptr<int> ptrB{ptrA};

	std::cout << ptrA << " " << *ptrA << std::endl;
	std::cout << ptrB << " " << *ptrB << std::endl;
	return 0;
}

输出:
00BB6120 5
00BB6120 5

use_count()

获取一个有多少个指针来调用当前对象:

long std::shared_ptr.use_count();

会返回当前指针共有多少对象调用。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include<iostream>
int main()
{
	int* a{};
	std::shared_ptr<int> ptrA{ new int{5} };
	std::shared_ptr<int> ptrB{ptrA};
	std::shared_ptr<int> ptrC{ptrA};
	std::shared_ptr<int> ptrD{ptrA};
	std::shared_ptr<int> ptrE{ptrA};

    // 获取当前有多少指针指向ptrA
	long use_count{ ptrA.use_count() };

	std::cout << ptrA << " " << *ptrA << std::endl;
	std::cout << ptrB << " " << *ptrB << std::endl;
	std::cout << use_count << std::endl;
	return 0;
}

输出:
00D89E48 5
00D89E48 5
5

unique()

将会返回一个bool值,如果当前智能指针是唯一拥有该指针的,那么返回true,否则返回false;

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include<iostream>
int main()
{
	int* a{};
	std::shared_ptr<int> ptrA{ new int{5} };
	// 获取当前有多少指针指向ptrA
	int use_count{ ptrA.unique() };
	std::cout << use_count << std::endl;

	std::shared_ptr<int> ptrB{ptrA};
	std::shared_ptr<int> ptrC{ptrA};
	std::shared_ptr<int> ptrD{ptrA};
	std::shared_ptr<int> ptrE{ptrA};

	// 获取当前有多少指针指向ptrA
	use_count = ptrA.unique();

	std::cout << ptrA << " " << *ptrA << std::endl;
	std::cout << ptrB << " " << *ptrB << std::endl;
	std::cout << use_count << std::endl;
	return 0;
}

输出:
1
00EEF6C8 5
00EEF6C8 5
0

reset()

std::shared_ptr.reset()

reset()会将当前共享指针设置为nullptr,同事如果当前智能指针是最后一个拥有该指针的对象,那么将会释放内存。



相关内容

0%