1. 智能指针作用
智能指针(类模板):问作用就是防止内存泄露
引入头文件
常用的四个智能指针为:auto_ptr、shared_ptr、weak_ptr、unique_ptr
- 有new没有delete,一定会造成内存泄露;一个new只能delete一次(空指针除外)
- std::auto_ptr:C++98提出,允许赋值,赋值给另一个auto_ptr时原来的指针变为空,不能访问(访问会崩溃),目前被unique_ptr取代(不允许)
- std::shared_ptr:共享指针(共享所有权),多个指针指向同一个对象(引用计数),最后一个被销毁,对象才被释放(多个指针指向同一个对象)
- std::weak_ptr:辅助shared_ptr工作,“弱”指针(弱共享、弱引用),绑定shared_ptr不改变强引用计数,使用弱引用次数
- std::unique_ptr:独占式指针,同一时间只有一个指针指向一个对象,所有权可以移交
2. new和delete
问作用就是动态申请和释放内存
- new:动态分配内存;delete:释放内存;成对使用;delete后的指针变成了悬空指针,不能操作了,但是仍然保存指向原来动态内存的地址,建议加上=pullptr。
int *p = new int(100);
delete p;
p = nullptr;
int *ptr = new int[100];
delete []ptr;
ptr = nullptr;
3. shared_ptr
### 普通指针
int *pi = new int(100);
shared_ptr<int> pi = new int(100);
### 智能指针
shared_ptr<int> pi(new int(100));
shared_ptr<int> pi = std::make_shared<int>(100)
auto p1 = std::make_shared<int>(100);
auto p2(p1);
void func(shared_ptr<int> tmp) {
return ;
}
void func(shared_ptr<int>& tmp) {
return ;
}
func(p2);
auto p3 = func(p2);
p3 = std::make_shared_ptr<int>(200);
p2 = std::make_shared_ptr<int>(200);
p2 = std::make_shared_ptr<int>(100);
auto p4 = std::make_shared_ptr<int>(200);
auto p5 = std::make_shared_ptr<int>(200);
p4 = p5;
#1 use_count() 引用计数的个数
auto p = std::make_shared_ptr<int>(200);
count = p.use_count();
# unique() 判断是否独占指针
shared_ptr<int> myp(new int (100));
if(myp.unique()) {}
auto myp1(myp);
if(myp.unique()) {}
# reset 不带参数
shared_ptr<int> myp(new int (100));
myp.reset();
shared_ptr<int> myp(new int (100));
auto myp1(myp);
myp.reset();
# reset 带参数
shared_ptr<int> myp(new int (100));
auto myp1(myp);
myp.reset(new int(1));
# *解引用,获得指针指向的对象
shared_ptr<int> pother(int new(100))
*pother
# get() 返回保存的指针(内置的裸指针)
shared_ptr<int> myp(new int(100));
int *p = myp.get();
*p = 45;
# swap() 交换两个智能指针所指向的对象,引用计数不发生变化
shared_ptr<string> ps1(new string("I love China1!"));
shared_ptr<string> ps1(new string("I love China2!"));
std::swap(ps1, ps2);
ps1.swap(ps2);
# 智能指针的名字作为判断条件
shared_ptr<string> ps1(new string("I love China!"));
if(ps1) {}
# 指定删除器和数组问题,自己定义delete函数 ### 可以通过模板来封装指定删除器数组
void myDeleter(int *p) {
delete p;
}
shared_ptr<int> p(new int(100), myDeleter);
shared_ptr<int> p(new int(100), [](int *p){
delete p;
});
shared_ptr<A> pA(new A[10]);
shared_ptr<A> pA(new A[10], [](int *p){
delete []p;
})
# 提倡使用make_shared来生成shared_ptr,但是这种方式无法自己指定删除器
#1 慎用裸指针,也不要用裸指针初始化多个shared_ptr
int *p = new int(100)
proc(shared_ptr<int>(p))
*p = 45
#2 慎用get返回的裸指针
#3 使用enable_shared_from_this(类模板)返回this
#4 避免循环引用
#include <iostream>
#include <string>
#include <cstdlib>
#include <memory>
class Test
{
private:
public:
Test() {
std::cout << "gou zao" << std::endl;
}
Test *Print1() {
std::cout << "print 1" << std::endl;
return this;
}
void Print2() {
std::cout << "print 2" << std::endl;
}
~Test() {
std::cout << "xi gou" << std::endl;
}
};
class Testa;
class Testb;
class Testa
{
public:
std::weak_ptr<Testb> m_pbs;
Testa() {
std::cout << "执行Testa 构造" << std::endl;
}
~Testa(){
std::cout << "执行Testa 析构" << std::endl;
}
};
class Testb
{
public:
std::shared_ptr<Testa> m_pas;
Testb() {
std::cout << "执行Testa 构造" << std::endl;
}
~Testb(){
std::cout << "执行Testa 析构" << std::endl;
}
};
int main() {
std::cout << "hello world!!!" << std::endl;
Test *a = new Test();
a->Print1()->Print2();
delete a;
a = nullptr;
std::shared_ptr<Testa> pca(new Testa);
std::shared_ptr<Testb> pcb(new Testb);
pca->m_pbs = pcb;
pcb->m_pas = pca;
return 0;
}
- 运行结果
4. weak_ptr
auto pi = make_shared<int>(100);
weak_ptr<int> piw(pi);
weak_ptr<int> piw1;
piw1 = piw;
# lock() 检查weak_ptr指向的对象是否存在,存在返回共享对象的shared_ptr(强引用计数加1),否则返回空的shared_ptr
auto piw2 = piw.lock();
# use_count() 获取与该弱指针共享对象的其他shared_ptr,即强引用计数的大小
auto pi = make_shared<int>(100);
auto pi1(pi);
weak_ptr<int> piw(pi);
int count = piw.use_count();
# expired() 判断是否过期(观测对象是否释放),use_count为0返回true,否则为false
pi.reset();
pi1.reset();
if(piw.expired()) {}
# reset() 将弱引用指针置为空,弱引用次数减1,强引用次数不变
auto pi = make_shared<int>(100);
weak_ptr<int> piw(pi);
piw.reset()
# lock() 检查weak_ptr指向的对象是否存在
# weak_ptr和shared_ptr指针对象的大小是相同,是弱指针的两倍(包含指向对象的指针和指向控制块的指针(引用计数、自定义删除器等))
shared_ptr<int> pi(new int (100));
weak_ptr<int> piw(pi);
int len1 = sizeof(pi);
int len2 = sizeof(piw);
5. unique_ptr
# 常规初始化,和new配合
unique_ptr<int> pi;
unique_ptr<int> pi(new int(100));
# make_unique函数(C++11没有,C++14开始引入),优先选择,具有更高的性能,不支持自定义删除器
unique_ptr<int> p1 = std::make_unique<int>(100);
auto p2 = std::make_unique<int>(200);
# 不支持复制,赋值操作
unique_ptr<string> ps1(new string("I love China!"));
unique_ptr<string> ps2(ps1);
unique_ptr<string> ps3 = ps1;
unique_ptr<string> ps4;
ps4 = ps1
# 移动语义 支持移动
unique_ptr<int> pi(new int(100));
unique_ptr<int> pi1 = std::move(pi);
# release() 放弃对指针的控制权,返回空的裸指针
unique_ptr<int> pi(new int(100));
unique_ptr<int> pi1(pi.release());
pi1.release()
string *tmp = ps1.release();
delete tmp;
# reset() 不带参数释放指针对象,并置为空;带参数重新指向新内存
# = nullptr 释放指针对象,并置为空
# 指向一个数组
unique_ptr<int[]> pi(new int[10])
pi[0] = 1;
pi[1] = 2;
# get() 返回智能指针中保存的对象(裸指针)
# *解应用
# swap() 交换指针所指向的对象
# 名字可用于判断
# 转成shared_ptr,如果unique_ptr为右值,可以赋值给shared_ptr,调用了shared_ptr的显示构造函数,接管unique_ptr所拥有的对象
unique_ptr<int> pi(new int(100));
shared_ptr<int> pi1 = std::move(pi);