【C++ 语言】智能指针 引入 ( 内存泄漏 | 智能指针简介 | 简单示例 )
I . 智能指针 引入
1 . 示例前提 : 定义一个 Student 类 , 之后将该类对象作为智能指针指向的对象 ;
class Student {
public:
//构造函数
Student()
{
cout << "Student 对象创建" << endl;
}
//析构函数
~Student()
{
cout << "Student 对象释放" << endl;
}
};
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
2 . 栈内存创建对象 : 如果在栈内存中创建对象 , 在方法结束后 , 会自动释放 Student 对象 ;
//栈内存中创建对象 , 在方法结束后 , 会自动释放 Student 对象
void createInStack() {
Student student;
}
- 1
- 2
- 3
- 4
- 5
- 6
3 . 堆内存创建对象 : 使用 new 在堆内存中创建对象时 , 在 该对象的 作用域 结束后 , 不会自动释放 Student 对象 ;
① 错误示例 : 如下方法中 , 只创建了对象 , 在作用域结束时 , 没有释放该对象 , 这样造成了内存泄漏 ;
//堆内存中创建对象 , 在方法结束后 , 不会自动释放 Student 对象
void createInHeap() {
Student *student = new Student;
}
- 1
- 2
- 3
- 4
- 5
- 6
② 正确示例 : 使用 new 关键字在堆内存中创建了对象 , 必须在作用域结束前, 将该对象使用 delete 方法释放掉 , 否则会造成内存泄漏 ;
//堆内存中创建对象 , 在方法结束后 , 手动调用 delete 释放 Student 对象
void createInHeapAndDelete() {
//在堆内存中创建对象
Student* student = new Student;
//手动释放 堆内存中创建的对象
delete(student);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
4 . 堆内存创建对象 使用智能指针指向该对象 : 堆内存中创建对象 , 将对象指针设置成智能指针 , 该对象在方法结束时会自动释放 ;
//堆内存中创建对象 , 将对象指针设置成智能指针 , 该对象在方法结束时会自动释放
void createInHeapWithSmartPointer() {
Student* student = new Student;
shared_ptr<Student> shared_student(student);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
II . 智能指针 简介
C ++ 的 STL ( Standard Template Library 标准模板库 ) 提供了 四种智能指针 :
① shared_ptr : 指向的对象所有权 共享 , 多个指针指向同一个对象 ; 当最后一个智能指针销毁时 , 对象销毁 ;
② weak_ptr : 为了弥补 shared_ptr 的缺陷而引入的智能指针 ;
③ unique_ptr : 指向的对象所有权 互斥 , 同一时间 , 一个 对象 只能有一个 unique_ptr 智能指针 指向它 ;
④ auto_ptr ( 已弃用 ) : 该智能指针在 C++ 11 标准中 已弃用 , 但是为了向低版本兼容 , 目前仍可以使用 ;
写新代码就不要使用
auto_ptr类型的智能指针了 , 推荐使用 unique_ptr 智能指针 , 该指针是 auto_ptr 的安全进阶版本 ;
III . 智能指针 简单示例
1 . 示例项目下载地址 :
主要代码及逻辑都在下面的主代码示例中 , 没有下载的必要 ;
2 . 头文件 :
// 007_SmartPointer.h: 标准系统包含文件的包含文件
// 或项目特定的包含文件。
#pragma once
#include <iostream>
// TODO: 在此处引用程序需要的其他标头。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
3 . 主代码示例 :
// 007_SmartPointer.cpp: 定义应用程序的入口点。
//
#include "007_SmartPointer.h"
using namespace std;
//智能指针原理 :
// 智能指针本质 : 智能指针也是一个对象
// 智能指针存放 : 该智能指针对象处于 栈内存中
// 智能指针释放 : 函数执行完毕后 , 就会调用智能指针对象的析构方法
// 判定引用计数 : 在智能指针对象析构方法的内部就会判定智能指针 操作对象 的引用计数
// 如果这个 操作对象的 引用计数为 0 , 就会调用 delete 方法释放 操作对象 ;
class Student {
public:
//构造函数
Student()
{
cout << "Student 对象创建" << endl;
}
//析构函数
~Student()
{
cout << "Student 对象释放" << endl;
}
};
//栈内存中创建对象 , 在方法结束后 , 会自动释放 Student 对象
void createInStack() {
Student student;
}
//堆内存中创建对象 , 在方法结束后 , 不会自动释放 Student 对象
void createInHeap() {
Student *student = new Student;
}
//堆内存中创建对象 , 在方法结束后 , 手动调用 delete 释放 Student 对象
void createInHeapAndDelete() {
//在堆内存中创建对象
Student* student = new Student;
//手动释放 堆内存中创建的对象
delete(student);
}
//堆内存中创建对象 , 将对象指针设置成智能指针 , 该对象在方法结束时会自动释放
void createInHeapWithSmartPointer() {
Student* student = new Student;
shared_ptr<Student> shared_student(student);
}
//堆内存中创建对象 , 将对象指针设置成智能指针 , 该对象在方法结束时会自动释放
void createInHeapWithTwoSmartPointer() {
Student* student = new Student;
//声明了一个智能指针对象 , student 的引用计数变成 1
shared_ptr<Student> shared_student1(student);
//又声明了第二个智能指针对象 , student 的引用计数 变成 2
shared_ptr<Student> shared_student2(student);
//上面的两个智能指针对象处于栈中 , 当函数结束时 , 这两个智能指针本身会被释放掉
// 释放两个智能指针后 , student 对象的引用计数又变成了 0
// 两个智能指针会被回收 , 回收智能指针时 , 会做判定 , 当 对象的引用计数为 0 时
// 自动调用该对象的析构函数 , 释放该对象
}
int main()
{
//C++ 11 STL 提供了两种类型的 智能指针
//在方法中 , 有两种创建对象的方式 : ① 直接声明对象 , ② 使用 new 创建对象 ;
// 直接声明对象 , 是在栈内存中创建实例 , 方法结束后 , 该实例自动释放 ;
// 如果使用 new 创建对象 , 是在堆内存中创建 , 创建后返回一个对象的指针 ;
// 堆内存中的对象需要手动释放 , new 申请的对象 , 需要调用 delete 释放 ( delete 会触发虚构函数 ) ;
// 如果忘记手动释放使用 new 创建的对象 , 就会导致内存泄漏
// 因此引入智能指针 , 可以防止忘记手动释放对象导致内存泄漏
//栈内存中创建对象 , 自动释放 Student 对象
cout << "栈内存中 创建 Student 对象" << endl;
createInStack();
//堆内存中创建对象 , 不会自动释放 Student 对象
cout << "\n堆内存中 创建 Student 对象 , 不主动释放该对象" << endl;
createInHeap();
cout << "\n堆内存中 创建 Student 对象 , 主动 调用 delete 方法 释放该对象" << endl;
//堆内存中创建对象 , 函数结束前手动调用 delete 方法 , 释放该对象
createInHeapAndDelete();
cout << "\n堆内存中 创建 Student 对象 , 将其设置成智能指针" << endl;
//堆内存中创建对象 , 将对象指针设置成智能指针 , 该对象在方法结束时会自动释放
createInHeapWithSmartPointer();
//智能指针分类 :
// 共享智能指针 : shared_ptr , 该智能指针内部实现了引用计数 , 多个共享智能指针指向同一个对象时
// 有 N 个 共享 智能指针同一个对象 , 其引用计数为 N
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
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
运行结果 :
栈内存中 创建 Student 对象
Student 对象创建
Student 对象释放
堆内存中 创建 Student 对象 , 不主动释放该对象
Student 对象创建
堆内存中 创建 Student 对象 , 主动 调用 delete 方法 释放该对象
Student 对象创建
Student 对象释放
堆内存中 创建 Student 对象 , 将其设置成智能指针
Student 对象创建
Student 对象释放
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
文章来源: hanshuliang.blog.csdn.net,作者:韩曙亮,版权归原作者所有,如需转载,请联系作者。
原文链接:hanshuliang.blog.csdn.net/article/details/104033227
- 点赞
- 收藏
- 关注作者
评论(0)