Author: XFFer_
1 直接内存管理(new/delete)
2 创建新工程,观察内存泄漏
C语言中是
malloc/free
int *pointi = new int(100);
string *points = new string(5, 'a'); //"aaaaa"
vector<int> *pointv = new vector<int>{1, 2, 3, 4, 5};
概念 “值初始化”:用()
来初始化
int *pointi = new int();
auto pointi_t = new auto(pointi);
//前面的auto推断出的是int **
推荐在delete
后将该指针设置成nullptr
C++中出现了智能指针,会帮助程序猿收回内存。
MFC应用程序能够在一定程度上(程序推出的时候),帮助发现内存泄漏。
MFC:微软公司出的基础的程序框架(MFC基础类库),可以生成一个带窗口(带界面)的程序框架,MFC简化了很多界面开发工作。
快捷键 ctrl + ]
跳转到对应的{
或 }
1 new/delete探秘
new/delete是什么
operator new()和operator delete()
基本new如何记录分配的内存大小供delete使用
申请和释放一个数组
为什么new/delete、new[]/delete[]要配套使用2 智能指针总述
3shared_ptr
基础常规初始化(
shared_ptr
和new
配合)
make_shared
函数
new/delete
类对象时,有初始化/释放的能力(调用构造函数/析构函数),这些是malloc/free
所不能的。
new/delete是操作符,operater new()和operator delete()是函数
new
简单理解为做了两件事:a)分配内存(实际上通过operator new()
);b)给内存初始化delete
也做了两件事:a)反初始化(调用析构函数);b)释放内存(operator delete()
)不同编译器new内部有不同的实现方式,new内部有记录机制,记录分配出多少内存。
int *p = new int[2];
delete[] p;
new
返回的指针,强大灵活,但是需要开发者全程维护。auto_ptr
(C++98)已经被unique_ptr取代unique_ptr
(C++11):独占式指针。同一时间内,只有一个指针指向该对象shared_ptr
(C++11):共享式指针。多个指针指向同一个对象,最后一个指针被销毁时,这个对象会被销毁weak_ptr
(C++11)用来辅助shared_ptr每个share_ptr的拷贝都指向相同的内存
工作原理:引用计数。只有最后一个指向该内存的shared_ptr
不需要再指向该对象时,才会析构这个对象。计数的作用是每增加一个shared_ptr
count + 1,销毁指针到count为0时,就会释放内存。
std::shared_ptr<int> pi(new int(100));
//智能指针explicit不允许隐式转换
//故std::shared_ptr pi = new int;是错误的
在自定义删除器时会受到限制
shared_ptr<int> pt = make_shared<int>(100);
1 shared_ptr引用计数的增加和减少
引用计数的增加
引用计数的减少2 shared_ptr指针常用操作
use_count()
unique()
reset()
*解应用
get()
swap()
=nullptr
智能指针名字作为判断条件
指定删除器以及数组问题
每个shared_ptr
都会记录有多少个其他的shared_ptr
指向相同的对象。
use_count()
:返回多少个智能指针指向某个对象,主要用于调试目的unique()
:是否该智能指针独占某个指向的对象,如果是,返回Truereset()
:复位/重置
*解应用
:获得指针指向的对象get()
:返回保存的指针(裸指针)。用于有些函数的参数需要的是一个内置裸指针而不是智能指针swap()
:交换两个智能指针所指向的对象=nullptr
//定义一个删除器函数
void deletefunc(int *p)
{
delete []p;
}
shared_ptr<int> pt(new int[100], deletefunc);
//打包
template<typename T>
shared_ptr<T> make_array(size_t n)
{
return shared_ptr<T>(new T[n], default_delete<T[]>());
}
shared_ptr pt = make_array<int>(3); //长度为3的整形数组,自定义删除器
//lambda函数做自定义删除器
shared_ptr<int> pt(new int[10], [](int *p) {
delete []p;
}
//default_delete做删除器
shared_ptr<int> pt(new int[10], default_delete<int[]>());
//C++17
shared_ptr<int[]> pt(new int[10]); //在<>中加[]
size_t
源码中 -> typedef unsigned __int64 size_t;
32位系统的size_t是4字节的unsigned int
64位系统的size_t是8字节的unsigned long long
unsigned int 0~4294967295
int -2147483648~2147483647
unsigned long 0~4294967295
long -2147483648~2147483647
long long的最大值:9223372036854775807
long long的最小值:-9223372036854775808
unsigned long long的最大值:18446744073709551615
__int64的最大值:9223372036854775807
__int64的最小值:-9223372036854775808
unsigned __int64的最大值:18446744073709551615
1 weak_ptr概述
weak_ptr的创建
2 weak_ptr常用操作
use_count()
expired()
reset()
lock()3 尺寸问题
weak_ptr
:用来辅助shared_ptr
进行工作。这个智能指针指向一个由shared_ptr
管理的对象。但是它并不控制所指向对象的生命周期(不会改变shared_ptr
的引用计数)。shared_ptr
能够照常释放所指向的对象。
一般都用shared_ptr
初始化。
auto pi = make_shared<int>(100);
weak_ptr<int> pwi(pi);
//不会改变强引用(strong ref)的引用计数,但是会增加弱引用(weak ref)计数
use_count
:获取当前所观测资源的强引用计数expired()
:是否过期,用来判断所观测资源是否被释放reset()
:将该弱引用指针设置为lock()
:功能是检查weak_ptr
所指向的对象是否存在。如果存在返回一个指向该对象的shared_ptr
,如果不存在则返回一个空的shared_ptr
//接着
auto pi2 = pwi.lock(); //会使强引用加1,pwi仍是弱引用
weak_ptr
的尺寸和shared_ptr
一样大,是裸指针的2倍(8字节)。实际上在它们内部包含了两个指针。
1
std::shared_ptr
使用场景
2std::shared_ptr
使用陷阱分析
3 性能说明尺寸问题
移动语义
enable_shared_from_this
(工作中需要返回该调用函数本身的类的智能指针时使用)
shared_from_this
时,实际上调用了这个weak_ptr的lock方法class CT : public enable_shared_from_this<CT>
{
public:
shared_ptr<CT> getself()
{
return shared_from_this(); //这个是enable_shared_from_this类模板中的方法
}
};
shared_ptr
和weak_ptr
均占8个字节,也就是两个指针,一个指针指向该指向对象的智能指针;一个指针指向控制块(包括强引用计数、弱引用计数、删除器、分配器等)
移动构造一个新的智能指针
shared_ptr<int> p1(new int(100));
shared_ptr<int> p2(std::move(p1));
会将p1指向的对象移动给p2,p1不再指向该对象(变成空指针)。
1 unique_ptr概述
常规初始化
make_unique函数2 unique_ptr常用操作
独占式的概念(专属所有权):同一个时刻只能有一个unique_ptr指向一个对象。当被销毁时,所指向的对象同时也被销毁。
unique_ptr<int> pt(new int(103));
//c++14:make_unique
unique_ptr<int> pt = make_unique<int>(104);
auto pt = make_unique<int>(105);
unique_ptr<string> ps1(new string("ingenious"));
unique_ptr<string> ps2(std::move(ps1));
release()
:放弃对指针的控制权,切断指针和对象之间的联系。返回裸指针,并将该智能指针置空,该裸指针需手动释放unique_ptr<string> ps1(new string("ingenuous"));
unique_ptr<string> ps2(ps1.release());
reset()
unique_ptr<string> ps3(new string("fractious"));
ps3.reset(ps1.release());
= nullptr
:释放指向的对象并置空该智能指针get()
:返回智能指针中保存的裸指针swap()
:交换两个指针所指向的对象shared_ptr
形式:如果unique_ptr为右值就可以转换成shared_ptr形式auto func()
{
return unique_ptr<string> st(new string("fd")); //返回的是临时对象,是右值
}
shared_ptr<string> p = func();
1 返回unique_ptr
2 指定删除器
3 尺寸问题
4 智能指针总结
格式: unique_ptr<指向的对象类型, 删除器类型> 指针名
void mydelete(string* p)
{
delete p;
p = nullptr;
}
//typedef void (*pr) (string *);
//using pr = void (*) (string *);
typedef decltype(mydelete)* pr;
unique_ptr<string, pr> point(new string("hei"), mydelete);
unique_ptr自定义删除器需要在模板参数中加入删除器函数的类型,例中提供了用函数指针做模板参数的情况。
通常情况下,unique_ptr和裸指针的大小一样(4字节)。但是自定义删除器就可能增加所占用的内存。