C++智能指针
- 1.智能指针是用对象的方式管理指针,所谓的智能体现在不需要主动释放new的内存,实质是通过析构函数自动调用的特性实现的,在使用智能指针的时候一般都是构建对象,不是new一个对象
- 2.当类中有指针成员时,一般有两种方式来管理指针成员:一是采用值型的方式管理,每个类对象都保留一份指针指向的对象的拷贝;另一种更优雅的方式是使用智能指针,从而实现指针指向的对象的共享。
- 3.智能指针(smart pointer)的一种通用实现技术是使用引用计数(reference count)。智能指针类将一个计数器与类指向的对象相关联,引用计数跟踪该类有多少个对象的指针指向同一对象。
1.共享型智能指针
shared_ptr是共享型智能指针,允许共享对象所有权
#include<iostream>
#include<string>
#include<memory>
#include<vector>
#include<cstdio>
using namespace std;
void testOne()
{
shared_ptr<int> p1; //无参构造
if (!p1)
{
cout << "空的智能指针对象" << endl;
//return;
}
shared_ptr<int> p2(new int(123));
//shared_ptr<int> p2=new int(123); 错误
shared_ptr<int> p3 = make_shared<int>(1234);
//怎么访问数据
//直接把智能指针当作指针即可
cout << *p3 << endl;
//cout<<p3[0]<<endl; //错误,没有下标法使用方式
//获取管理对象的原生指针
int* pNum = p3.get();
cout << *pNum << endl;
cout << pNum[0] << endl;
//获取到原生指针的时候千万不要自己释放
//成员函数:use_count()
cout << "管理对象数:" << p3.use_count() << endl;
shared_ptr<int> p4(p3);
cout << "管理对象数:" << p3.use_count() << endl;
}
class MM
{
public:
MM(string name,int age):name(name),age(age){}
MM(string name):name(name),age(0){}
MM() :name(""), age(0){};
void print()
{
cout << name << "\t" << age << endl;
}
~MM()
{
cout << "释放成功" << endl;
}
protected:
string name;
int age;
};
void testTwo()
{
shared_ptr<MM> pMM(new MM("name1", 18));
pMM->print();
vector<MM*> arr;
//arr.push_back(new MM("name1", 20)); 释放不了,存在内存泄露
//实际应用比较多的写法
vector<shared_ptr<MM>> arr2;
shared_ptr<MM> p(new MM("name2", 20));
arr2.push_back(p);
shared_ptr<MM> pMM2 = make_shared<MM>("name3", 30);
pMM2->print();
}
//管理一段内存
void testThree()
{
shared_ptr<int> p(new int[4]{1,2,3,4});
//不行,但可以用原生指针去操作
//for (int i = 0; i < 4; i++)
//{
// cout << *(p + i) << endl;
//}
//cout << endl;
int* pNum = p.get();
for (int i = 0; i < 4; i++)
{
cout << *(pNum + i) << " ";
}
cout << endl;
//手动删除的情况,
//特殊内存
//delete []pMM;
//c语言文件指针 fopen搞内存 free释放
shared_ptr<MM> pMM(new MM[4], [](MM*& pMM){ delete[] pMM; });
shared_ptr<FILE> pfile(fopen("1.txt", "w+"), [](FILE*& file) {free(file); });
}
//可以当函数参数
void printMM(shared_ptr<MM> pMM)
{
pMM->print();
}
//可以当函数返回值
shared_ptr<int> returnPoint(int num)
{
return shared_ptr<int>(new int[num]);
}
int main()
{
testOne();
testTwo();
testThree();
return 0;
}
2.弱引用型智能指针
weak_ptr弱引用型指针,不会累计计数,存在的意义是为了解决share_ptr导致的循环引用问题
- 1.weak_ptr只能从shared_ptr或者已有的weak_ptr去构造,不能直接管理对象
- 2.不能直接访问管理对象(*或者->访问)
- 3.访问数据的方式只能通过lock函数访问share_ptr 然后再去访问数据
#include<iostream>
#include<memory>
using namespace std;
class B;
class A
{
public:
~A()
{
cout << "A" << endl;
}
weak_ptr<B> a;
};
class B
{
public:
~B()
{
cout << "B" << endl;
}
weak_ptr<A> b;
};
void testLoopUse()
{
shared_ptr<A> ao(new A);
shared_ptr<B> bo(new B);
//形成一个循环,用弱引用型指针可以释放
ao->a = bo;
bo->b = ao;
}
void test_weak_ptr()
{
//1.weak_ptr只能从shared_ptr或者已有的weak_ptr去构造,不能直接管理对象
//2.不能直接访问管理对象(*或者->访问)
//3.访问数据的方式只能通过lock函数访问share_ptr 然后再去访问数据
shared_ptr<int> p(new int(123));
cout << "count:" << p.use_count() << endl;
weak_ptr<int> w(p);
cout << "count:" << w.use_count() << endl; //不会引起计数的改变
weak_ptr<int> w2(w);
cout << "count:" << w2.use_count() << endl; //不会引起计数的改变
//访问数据
cout << *w.lock() << endl;
shared_ptr<int> object = w.lock();
cout << *object << endl;
}
int main()
{
testLoopUse();
test_weak_ptr();
return 0;
}
3.独享型智能指针
unique_ptr 独享型就是一个对象永远都只有一个智能对象管理,实现本质是禁止拷贝,禁止复制
一般传参的话都是传引用
想要复制,可以:
- move函数转交所有权
- 通过reset函数 结合release函数转交所有权
#include<iostream>
#include<memory>
using namespace std;
void testOne()
{
unique_ptr<int> p1(new int(1234));
cout << *p1 << endl;
unique_ptr<int> p2;
//p2 = p1; //错误的
//unique_ptr<int> p3(p1); //错误的
p2 = move(p1);
cout << *p2 << endl;
//cout << *p1 << endl; //错误的,p1失去了管理对象
unique_ptr<int> p3(new int(456));
p3.reset(p2.release());
cout << *p3 << endl;
}
class MM
{
public:
MM(){}
void print()
{
cout << "打印测试" << endl;
}
~MM() { cout << "析构完成" << endl; }
protected:
};
void testTwo()
{
//unique_ptr 删除器写法,需要手动写入删除器的类型
unique_ptr<MM,void(*)(MM*&)> pMM(new MM[4], [](MM*& pMM) {delete[] pMM; });
using FUNC = void(*)(MM*&);
unique_ptr<MM, FUNC> pMM2(new MM[4], [](MM*& pMM) {delete[] pMM; });
}
//传参一般都是传引用
void printUnique(unique_ptr<MM>& pMM)
{
pMM->print();
}
int main()
{
testOne();
testTwo();
unique_ptr<MM> pMM(new MM);
printUnique(pMM);
return 0;
}