c++智能指针
简介
c++没有自动回收的机制,需要程序猿new一个空间,同时delete掉一个空间,免的造成内存的泄露。
智能指针就能有效的解决这一问题。
具体使用
对于编译器来说,智能指针实际上是一个栈对象,并非指针类型,在栈对象生命期即将结束时,智能指针通过析构函数释放有它管理的堆内存。所有智能指针都重载了“operator->”操作符,直接返回对象的引用,用以操作对象。访问智能指针原来的方法则使用“.”操作符。
C++11 中智能指针包括以下三种:
C++11 中智能指针包括以下三种:
-
共享指针(shared_ptr):资源可以被多个指针共享,使用计数机制表明资源被几个指针共享。通过 use_count()查看资源的所有者的个数,可以通过 unique_ptr、weak_ptr 来构造,调用 release()释放资源的所有权,计数减一,当计数减为 0 时,会自动释放内存空间,从而避免了内存泄漏。
-
独占指针(unique_ptr):独享所有权的智能指针,资源只能被一个指针占有,该指针不能拷贝构造和赋值。但可以进行移动构造和移动赋值构造(调用
move() 函数),即一个 unique_ptr 对象赋值给另一个 unique_ptr 对象,可以通过该方法进行赋值。 -
弱指针(weak_ptr):指向 share_ptr 指向的对象,能够解决由shared_ptr带来的循环引用问题。
使用智能指针可能出现的问题
循环引用
#include <iostream>
#include <memory>
using namespace std;
class Child;
class Parent;
class Parent {
private:
shared_ptr<Child> ChildPtr;
public:
void setChild(shared_ptr<Child> child) {
this->ChildPtr = child;
}
void doSomething() {
if (this->ChildPtr.use_count()) {
}
}
~Parent() {
}
};
class Child {
private:
shared_ptr<Parent> ParentPtr;
public:
void setPartent(shared_ptr<Parent> parent) {
this->ParentPtr = parent;
}
void doSomething() {
if (this->ParentPtr.use_count()) {
}
}
~Child() {
}
};
int main() {
weak_ptr<Parent> wpp;
weak_ptr<Child> wpc;
{
shared_ptr<Parent> p(new Parent);
shared_ptr<Child> c(new Child);
p->setChild(c);
c->setPartent(p);
wpp = p;
wpc = c;
cout << p.use_count() << endl; // 记数为2
cout << c.use_count() << endl; // 记数为2
}
cout << wpp.use_count() << endl; // 记数为1
cout << wpc.use_count() << endl; // 记数为1
return 0;
}
使用weak_ptr,weak_ptr只能拥有shared_ptr的观测权,没有使用权,想要使用的时候,就将weak_ptr转为shared_ptr,这个时候新产生的shared_ptr对象是不会引起循环引用的问题,因为它在它的作用域结束后肯定要释放的,和weak_ptr所在的类对象没有任何关系了。weak_ptr不会增加次数,相当于在循环中断了一条链,这样两边的内存就能同时释放。
#include <iostream>
#include <memory>
using namespace std;
class Child;
class Parent;
class Parent {
private:
//shared_ptr<Child> ChildPtr;
weak_ptr<Child> ChildPtr;
public:
void setChild(shared_ptr<Child> child) {
this->ChildPtr = child;
}
void doSomething() {
//new shared_ptr
if (this->ChildPtr.lock()) {
}
}
~Parent() {
}
};
class Child {
private:
shared_ptr<Parent> ParentPtr;
public:
void setPartent(shared_ptr<Parent> parent) {
this->ParentPtr = parent;
}
void doSomething() {
if (this->ParentPtr.use_count()) {
}
}
~Child() {
}
};
int main() {
weak_ptr<Parent> wpp;
weak_ptr<Child> wpc;
{
shared_ptr<Parent> p(new Parent);
shared_ptr<Child> c(new Child);
p->setChild(c);
c->setPartent(p);
wpp = p;
wpc = c;
cout << p.use_count() << endl; // 2
cout << c.use_count() << endl; // 1
}
cout << wpp.use_count() << endl; // 0
cout << wpc.use_count() << endl; // 0
return 0;
}