在c++开发中,我们在堆区开辟空间创建对象后,经常做一些业务逻辑后,忘记将堆区的对象释放掉,这一点不像java可以自动释放。所以C++推出了只能指针。接下来一起认识一下:
主要介绍三个:
1) shared_ptr
2) weak_ptr
3) unique_ptr
说明:
**引入库:#include <memory>** **格式:shared_ptr<类型> sharedPtr1(堆区开辟的对象指针);** **1、当我们在堆区开辟空间后,需要在函数弹栈之前释放堆区空间,经常因为业务逻辑导致忘记释放,这时候使用智能指针就会帮助我们释放(堆区开辟空间后马上加入到智能指针中去就可以了)** **2、智能指针是使用引用计数的方式进行管理对象的,当计数等于0 的时候,就会释放对象** **3、原理:智能指针是栈成员,函数弹栈--->释放智能指针成员--->调用它的析构函数对对象进行释放(计数-1)**
示例代码:
#include <memory>
class Person{
public:
~Person() {
cout << "Person 析构函数" << endl;
}
};
int main(){
Person* person=new Person();
shared_ptr<Person> sharedPtr(person);
return 0;
}
/**
Person 析构函数
*/
<u>上述代码为什么会调用析构函数呢?我们并没有调用delete person,而person又是在堆区开辟的,这是为什么呢?</u>
<u>这是因为智能指针帮我们做了,我们将新new出来的对象指针交给了智能指针,智能指针是栈成员,而栈成员在main函数弹栈时,会被调用智能指针的析构函数,析构函数判断对象person的引用不等于0 ,就会调用person的析构函数释放person对象,从而达到释放堆空间的目的。</u>
是不是very beautiful ?????现实总是很残酷,看看下面的示例就知道:
class Person2;
class Person1 {
public:
shared_ptr<Person2> person2; // Person2智能指针 shared_ptr 引用计数+1
~Person1() {
cout << "Person1 析构函数" << endl;
}
};
class Person2 {
public:
shared_ptr<Person1> person1; // Person1智能指针 shared_ptr 引用计数+1
~Person2() {
cout << "Person2 析构函数" << endl;
}
};
int main(){
Person1 * person1 = new Person1(); // 堆区开辟
Person2 * person2 = new Person2(); // 堆区开辟
shared_ptr<Person1> sharedPtr1(person1); // +1 = 1
shared_ptr<Person2> sharedPtr2(person2); // +1 = 1
cout << "前 sharedPtr1的引用计数是:" << sharedPtr1.use_count() << endl;
cout << "前 sharedPtr2的引用计数是:" << sharedPtr2.use_count() << endl;
// 给Person2智能指针赋值
person1->person2 = sharedPtr2;
// 给Person1智能指针赋值
person2->person1 = sharedPtr1;
cout << "后 sharedPtr1的引用计数是:" << sharedPtr1.use_count() << endl;
cout << "后 sharedPtr2的引用计数是:" << sharedPtr2.use_count() << endl;
return 0;
}
//前 sharedPtr1的引用计数是:1
//前 sharedPtr2的引用计数是:1
//后 sharedPtr1的引用计数是:2
//后 sharedPtr2的引用计数是:2
引用计数进行赋值操作后变成2 ,最后析构函数都没有执行!!!!!
这就是shared_ptr智能指针存在的循环依赖,导致引用计数减1 后,引用计数不会变成0 ,导致释放的时候无法释放。
这时候我们需要使用另外一个智能指针weak_ptr 来解决循环依赖的问题,因为他内部是没有引用计数的。
weak_ptr 可以像java中弱引用来理解。
修改后的示例代码:
class Person2;
class Person1 {
public:
//TODO----------------下面一句进行了修改----------------------------
weak_ptr<Person2> person2; // Person2智能指针 shared_ptr 引用计数+1
~Person1() {
cout << "Person1 析构函数" << endl;
}
};
class Person2 {
public:
//TODO ----------------下面一句进行了修改----------------------------
weak_ptr<Person1> person1; // Person1智能指针 shared_ptr 引用计数+1
~Person2() {
cout << "Person2 析构函数" << endl;
}
};
int main(){
Person1 * person1 = new Person1(); // 堆区开辟
Person2 * person2 = new Person2(); // 堆区开辟
shared_ptr<Person1> sharedPtr1(person1); // +1 = 1
shared_ptr<Person2> sharedPtr2(person2); // +1 = 1
cout << "前 sharedPtr1的引用计数是:" << sharedPtr1.use_count() << endl;
cout << "前 sharedPtr2的引用计数是:" << sharedPtr2.use_count() << endl;
// 给Person2智能指针赋值
person1->person2 = sharedPtr2;
// 给Person1智能指针赋值
person2->person1 = sharedPtr1;
cout << "后 sharedPtr1的引用计数是:" << sharedPtr1.use_count() << endl;
cout << "后 sharedPtr2的引用计数是:" << sharedPtr2.use_count() << endl;
return 0;
}
/**
前 sharedPtr1的引用计数是:1
前 sharedPtr2的引用计数是:1
后 sharedPtr1的引用计数是:1
后 sharedPtr2的引用计数是:1
Person2 析构函数
Person1 析构函数
*/
接下来我们认识一下很自私的智能指针,unique_ptr ---- 独占式智能指针,
class Person{
public:
~Person() {
cout << "Person 析构函数" << endl;
}
};
int main(){
Person* person3=new Person();
unique_ptr<Person> uniquePtr1(person3);
// unique_ptr<Person> uniquePtr2=uniquePtr1;//不能再次赋值,修改管理的指针
return 0;
}
//输出:Person 析构函数
今天对于智能指针的学习就到这里吧,毕竟笔者也没有使用过,今天和屏幕前面的你一样,也是在学习中,共勉吧!!!
网友评论