一 智能指针
1.1 手动初始化
注意:share_ptr<int> p = new int(10); //错误
share_ptr是explicit,不能进行隐式类型转换,只能直接初始化
1.1.1 make_shared
?
//功能:在堆区可以动态分配对象,并返回一个share_ptr(推荐,安全,高效)(构造方法初始化)
auto p = std::make_shared<string>("helloworld");
?
shared_ptr<int> p1 = make_shared<int>(5);
cout << *p1 << endl;
shared_ptr<string> ps = make_shared<string>("hello world");
cout << *ps << endl;
//手动初始化和使用make_shared函数模板初始化有什么区别?
//开销小,效率高(数据和引用计数存在同一个空间)
//构造函数初始化:数据和引用计数不再同一段空间,需要间接访问
?
shared_ptr<A> a1 = make_shared<A>();
shared_ptr<A> a2(a1);
1.2 常规操作
1.2.1 use_count()
功能:返回有多少个智能指针指向某个对象(引用计数的个数)
用途:主要用于调试
shared_ptr<A> a1 = make_shared<A>();
shared_ptr<A> a2(a1);
cout << a2.use_count() << endl; ?//返回当前有多少个指针指向当前对象或者空间
1.2.2 unique();
功能:是否该智能指针独占某个对象,独占返回true,否则返回false;
if (a1.unique()) ?//判断当前指针是否独享(只有它自己指向该对象)或者空间
{
cout << "a1 is unique ptr" << endl;
}
1.2.3 reset
功能:判断当前指针是否独享该对象,如果独享,则释放该对象,否则将该指针置为NULL,并将引用计数器减一
用法:reset()或者reset(参数)
//判断当前指针是否独享该对象,如果独享,则释放该对象,并使该指针指向形参所对应的空间
a1.reset(new A(10));
//shared_ptr<A> pa(new A(188));
//a1.reset(pa);
cout << a1->m_a << endl;
1.2.4 解引用
获取智能指针指向的对象,并对其操作
get(); //获取智能指针中保存的裸指针。
shared_ptr<int> pd = make_shared<int>(5);
Test(pd.get());
1.2.5 指定删除器
功能:有些情况,默认删除器处理不了(share_ptr管理的动态数组)
需要我们自己指定删除器,调用删除器函数释放空间
//指定删除器:当删除器不起作用的时候,需要自己指定删除器 void(*)(T*)
//shared_ptr<A> pa(new A[3]); //delete pa --->应该是delete []pa;
//shared_ptr<A[]> pa(new A[3]);
//shared_ptr<A> pa(new A[3], Mydelete);
shared_ptr<A> pa(new A[3], default_delete<A[]>());
1.2.6 lambda 表达式
shared_ptr<A> pa(new A[3], [](A*a) {
delete[]a; //lambda表达式
});
1.2.7 移动语义
shared_ptr<A> pa(new A(5));
const shared_ptr<A> &rpa = move(pa);
//shared_ptr<A> &&rpa = move(pa);
cout << "***************"<<endl;
//pa = nullptr;
cout << pa.use_count() << endl;
cout << rpa.use_count() << endl;
#include <iostream>
#include <memory>
#include <string>
using namespace std;
class A
{
public:
A()
{
cout << "A的无参构造" << endl;
}
A(int n)
{
m_a = n;
cout << "A的有参构造" << endl;
}
~A()
{
cout << "A的析构函数" << endl;
}
public:
int m_a;
};
shared_ptr<A> test()
{
shared_ptr<A> temp(new A);
return temp;
}
void Func(shared_ptr<A> temp)
{
cout << temp->m_a << endl;
}
void Test(int *p)
{
}
void Mydelete(A *pa)
{
delete[]pa;
}
int main(void)
{
#if 0
//int *p = new int(5); //p是裸指针
//shared_ptr<int> p = new int(5); //初始化:调用类型转换构造函数 explicit
shared_ptr<int> p(new int(5));
cout << *p << endl;
shared_ptr<string> s(new string("helloworld"));
cout << *s << endl;
int num = 100;
//shared_ptr<int> p2(&num); //智能指针常用于堆空间,指向栈空间的时候,会导致内存释放两次
//A *pa = new A(100);
//delete pa;
shared_ptr<A> pa(new A);
shared_ptr<A> res = test();
Func(pa);
shared_ptr<A> pa2(pa);
//功能:在堆区可以动态分配对象,并返回一个share_ptr(推荐,安全,高效)(构造方法初始化)
auto p = std::make_shared<string>("helloworld");
shared_ptr<int> p1 = make_shared<int>(5);
cout << *p1 << endl;
shared_ptr<string> ps = make_shared<string>("hello world");
cout << *ps << endl;
//手动初始化和使用make_shared函数模板初始化有什么区别?
//开销小,效率高(数据和引用计数存在同一个空间)
//构造函数初始化:数据和引用计数不再同一段空间,需要间接访问
//常规操作:
shared_ptr<A> a1 = make_shared<A>();
shared_ptr<A> a2(a1);
cout << a2.use_count() << endl; //返回当前有多少个指针指向当前对象或者空间
if (a1.unique()) //判断当前指针是否独享(只有它自己指向该对象)或者空间
{
cout << "a1 is unique ptr" << endl;
}
a1.reset();
if (a1 == nullptr) //NULL:void*() 0
{
cout << "a1 is nullptr" << endl;
}
cout << a2.use_count() << endl;
//判断当前指针是否独享该对象,如果独享,则释放该对象,并使该指针指向形参所对应的空间
a1.reset(new A(10));
//shared_ptr<A> pa(new A(188));
//a1.reset(pa);
cout << a1->m_a << endl;
shared_ptr<int> pd = make_shared<int>(5);
Test(pd.get());
#endif
//指定删除器:当删除器不起作用的时候,需要自己指定删除器 void(*)(T*)
//shared_ptr<A> pa(new A[3]); //delete pa --->应该是delete []pa;
//shared_ptr<A[]> pa(new A[3]);
//shared_ptr<A> pa(new A[3], Mydelete);
//shared_ptr<A> pa(new A[3], default_delete<A[]>());
/*shared_ptr<A> pa(new A[3], [](A*a) {
delete[]a; //lambda表达式
});*/
shared_ptr<A> pa(new A(5));
const shared_ptr<A> &rpa = move(pa);
//shared_ptr<A> &&rpa = move(pa);
cout << "***************"<<endl;
//pa = nullptr;
cout << pa.use_count() << endl;
cout << rpa.use_count() << endl;
return 0;
}
1.3 auto_ptr
#include <iostream>
#include <memory>
using namespace std;
class Test
{
public:
Test()
{
cout << "Test的构造函数" << endl;
}
void print()
{
cout << "hello world" << endl;
}
~Test()
{
cout <<"Test的析构函数"<<endl;
}
};
void func1()
{
Test *pt = new Test;
}
void func2()
{
auto_ptr<Test> pt(new Test);
pt->print(); //pt.operator->(print());
}
int main(void)
{
func2();
func2();
}
1.4 weak_ptr
1.4.1 概念
弱指针:不会控制对象的生命周期(不会改变对象的引用计数)。
share_ptr释放指向对象时,是不会考虑weak_ptr是否指向该对象。
weak_ptr不是独立指针,不能单独操作所指向的资源。
1.4.2 作用
weak_ptr指针一般用来辅助share_ptr的使用(监视share_ptr指向对象的生命周期)
weak_ptr和share_ptr可以相互转化,share_ptr可以直接赋值给weak_ptr
但是反过来是行不通的,需要使用lock函数。
1.4.3 常规操作
(1)lock函数
调用Lock函数用来获取share_ptr(如果对象已经被释放,则返回一个空的share_ptr)
shared_ptr<A> pa(new A(5));
pa.reset();
weak_ptr<A> wpa = pa;
auto pb = wpa.lock(); //将弱指针转为共享指针
if(nullptr == pb)
{
cout << "pb is nullptr" << endl;
}
else
{
cout << "pb is not nullptr" << endl;
}
(2)use_count
功能:返回有多少个weak_ptr智能指针指向对象(引用计数的个数)
用途:主要用于调试。
(3)expired
功能:判断弱指针是否过期(所检测的对象是否被释放 true /false)
//wpa.reset(); //弱引用计数-1,
cout << wpa.use_count() << endl; //返回的是weak_ptr的引用计数
cout << pb.use_count() << endl;
if (wpa.expired()) //判断当前弱指针指向的对象是否被释放,弱被释放,返回true,否则返回false
{
cout << "wpa poniter class is free" << endl;
}
(4) 循环引用
?
#include <iostream>
#include <memory>
#include <string>
using namespace std;
class Child;
class Parent;
class A
{
public:
A()
{
cout << "A的无参构造" << endl;
}
A(int n)
{
m_a = n;
cout << "A的有参构造" << endl;
}
~A()
{
cout << "A的析构函数" << endl;
}
public:
int m_a;
};
class Parent
{
public:
Parent()
{
cout << "Parent的构造函数" << endl;
}
~Parent()
{
cout << "parent的析构函数" << endl;
}
weak_ptr<Child> c;
};
class Child :public Parent
{
public:
Child()
{
cout << "Child的构造函数" << endl;
}
~Child()
{
cout << "Child的析构函数" << endl;
}
weak_ptr<Parent> p;
};
int main(void)
{
#if 0
//weak_ptr<A> wpa(new A(5)); //不能独立操作一块空间
shared_ptr<A> pa(new A(5));
//weak_ptr:类模板,弱指针(弱引用计数)
weak_ptr<A> wpa = pa;
weak_ptr<A> wpb = pa;
weak_ptr<A> wpc = pa; //弱引用不会影响其生命周期,无论多少个弱引用指向这段空间,只要强引用计数为0,则释放这段空间
//常规操作:
shared_ptr<Parent> pp(new Parent);
shared_ptr<Child> cc(new Child);
pp->c = cc;
cc->p = pp;
cout << "hello world" << endl;
#endif
shared_ptr<A> pa(new A(5));
//pa.reset();
weak_ptr<A> wpa = pa;
auto pb = wpa.lock(); //将弱指针转为共享指针
if(nullptr == pb)
{
cout << "pb is nullptr" << endl;
}
else
{
cout << "pb is not nullptr" << endl;
}
//wpa.reset(); //弱引用计数-1,
cout << wpa.use_count() << endl; //返回的是weak_ptr的引用计数
cout << pb.use_count() << endl;
if (wpa.expired()) //判断当前弱指针指向的对象是否被释放,弱被释放,返回true,否则返回false
{
cout << "wpa poniter class is free" << endl;
}
return 0;
}
(5) share_ptr & weak_ptr
尺寸:share_ptr 和 weak_ptr一样大,都是裸指针的两倍
?
#include <iostream>
#include <memory>
#include <string>
using namespace std;
class Child;
class Parent;
class A:public enable_shared_from_this<A>
{
public:
A()
{
cout << "A的无参构造" << endl;
}
A(int n)
{
m_a = n;
cout << "A的有参构造" << endl;
}
//A *GetAddr()
shared_ptr<A> GetAddr()
{
//return this;
//shared_ptr<A> tmp(this);
//return tmp;
//实现原理:
//其内部有一个weak_ptr类型的成员变量_wptr
//当shared_ptr构造的时候,如果其模板类型继承了enable_shared_from_this<T>,则堆_wptr进行初始化操作
//这样在调用shared_from_this()的时候,就能通过weak_ptr构造出对应的shared_ptr
return shared_from_this(); //和pa共享其所有权
}
~A()
{
cout << "A的析构函数" << endl;
}
public:
int m_a;
};
class Parent
{
public:
Parent()
{
cout << "Parent的构造函数" << endl;
}
~Parent()
{
cout << "parent的析构函数" << endl;
}
weak_ptr<Child> c;
};
class Child :public Parent
{
public:
Child()
{
cout << "Child的构造函数" << endl;
}
~Child()
{
cout << "Child的析构函数" << endl;
}
weak_ptr<Parent> p;
};
int main(void)
{
#if 0
//weak_ptr<A> wpa(new A(5)); //不能独立操作一块空间
shared_ptr<A> pa(new A(5));
//weak_ptr:类模板,弱指针(弱引用计数)
weak_ptr<A> wpa = pa;
weak_ptr<A> wpb = pa;
weak_ptr<A> wpc = pa; //弱引用不会影响其生命周期,无论多少个弱引用指向这段空间,只要强引用计数为0,则释放这段空间
//常规操作:
shared_ptr<Parent> pp(new Parent);
shared_ptr<Child> cc(new Child);
pp->c = cc;
cc->p = pp;
cout << "hello world" << endl;
shared_ptr<A> pa(new A(5));
//pa.reset();
weak_ptr<A> wpa = pa;
auto pb = wpa.lock(); //将弱指针转为共享指针
if(nullptr == pb)
{
cout << "pb is nullptr" << endl;
}
else
{
cout << "pb is not nullptr" << endl;
}
//wpa.reset(); //弱引用计数-1,
cout << wpa.use_count() << endl; //返回的是weak_ptr的引用计数
cout << pb.use_count() << endl;
if (wpa.expired()) //判断当前弱指针指向的对象是否被释放,弱被释放,返回true,否则返回false
{
cout << "wpa poniter class is free" << endl;
}
shared_ptr<int> p(new int(5));
cout << sizeof(p) << endl;
cout << sizeof(int *) << endl;
weak_ptr<int> wp = p;
cout << sizeof(wp) << endl;
#endif
//局部对象释放两次,A自己释放一次,share_ptr还会释放一次
/*A a;
shared_ptr<A> tmp = a.GetAddr();*/
/*
shared_ptr<A> GetAddr()
{
//return this;
shared_ptr<A> tmp(this);
return tmp;
}
*/
shared_ptr<A> pa(new A());
auto tmp = pa->GetAddr();
cout << pa.use_count() << endl;
cout << tmp.use_count() << endl;
int * pt = new int();
shared_ptr<int> spt1(pt);
shared_ptr<int> spt2(pt);
std::cout << "spt1.use_count() = " << spt1.use_count() << std::endl;
std::cout << "spt2.use_count() = " << spt2.use_count() << std::endl;
return 0;
}
1.4.4 总结
优点:防止内存泄漏
缺点:造成不必要的开销
|