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 数据类型;
数据类型* 指针变量名称 = new 数据类型[数量]
分配失败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
,同事如果当前智能指针是最后一个拥有该指针的对象,那么将会释放内存。