您的位置:首页 > 其它

shared_ptr的用法

2016-05-11 18:59 281 查看
先看一个例子:

#include <stdio.h>
#include <iostream>
#include <memory>
using namespace std;

class A
{
public:
A() { printf("A constructor\n"); }
~A() { printf("A destructor\n");  }

void Print() { printf("This is A\n"); }
};

int _tmain(int argc, _TCHAR* argv[])
{
shared_ptr<A> a(new A());
shared_ptr<A> b(new A());
a = b;
getchar();
return 0;
}


运行结果如下:

A constructor
A constructor
A destructor
上面的例子中创建了共享指针a和b,引用计数都是1,b赋值给a,此时a最初所指对象会被销毁,因为它的引用计数变为0,b所指的对象引用计数加1

另一个例子:

#include <stdio.h>
#include <iostream>
#include <memory>
#include <vector>
using namespace std;

class A
{
public:
A() { printf("A constructor\n"); }
~A() { printf("A destructor\n");  }

void Print() { printf("This is A\n"); }
};

void SP()
{
A* p = new A();
shared_ptr<A> a(p);
shared_ptr<A> b(p);
printf("a.use_count(): %d, b.use_count(): %d\n", a.use_count(), b.use_count());
}

int _tmain(int argc, _TCHAR* argv[])
{
SP();
getchar();
return 0;
}


运行结果如下:

A constructor
a.use_count(): 1, b.use_count(): 1
A destructor
A destructor


注意:上面代码运行输出以上结果后,还会弹出错误异常窗口

可以看出,a和b都关联到了p上,并且a和b的引用计数也是单独算的,都是1,这就导致函数退出的时候把p指向的对象销毁了两次,导致错误发生。

接着看例子:

#include <stdio.h>
#include <iostream>
#include <memory>
#include <vector>
using namespace std;

class A
{
public:
A() { printf("A constructor\n"); }
~A() { printf("A destructor\n");  }

void Print() { printf("This is A\n"); }
};

int _tmain(int argc, _TCHAR* argv[])
{
shared_ptr<A> a(new A());
A* p = a.get();
p->Print();
printf("a.use_count(): %d\n", a.use_count());
getchar();
return 0;
}


运行结果如下:

A constructor
This is A
a.use_count(): 1


share_ptr的成员函数get可以获取传统的C指针,此时引用计数仍然是1,不要对获取到的传统c指针进行delete操作,否则会发生错误

接下来的例子:

#include <stdio.h>
#include <iostream>
#include <memory>
#include <vector>
using namespace std;

class A
{
public:
A() { printf("A constructor\n"); }
~A() { printf("A destructor\n");  }

void Print() { printf("This is A\n"); }
};

int _tmain(int argc, _TCHAR* argv[])
{
shared_ptr<A> a(new A());
shared_ptr<A> b(a);
shared_ptr<A> c(b);
printf("a.use_count(): %d\n", a.use_count());
printf("b.use_count(): %d\n", b.use_count());
printf("c.use_count(): %d\n", c.use_count());
a.reset();
printf("\nAfter a.reset()\n");
printf("a.use_count(): %d\n", a.use_count());
printf("b.use_count(): %d\n", b.use_count());
printf("c.use_count(): %d\n", c.use_count());
getchar();
return 0;
}


运行结果如下:

A constructor
a.use_count(): 3
b.use_count(): 3
c.use_count(): 3

After a.reset()
a.use_count(): 0
b.use_count(): 2
c.use_count(): 2

调用reset后,a就不再跟之前绑定的指针有任何关系了(实际过程是a的内部成员变量_Ptr和_Rep都被置为0,通过创建临时变量再Swap),所以引用b和c的引用计数也都相应减1

make_shared的使用:

#include <stdio.h>
#include <iostream>
#include <memory>
#include <vector>
using namespace std;

class A
{
public:
A() { printf("A constructor\n"); }
A(int a): m_a(a) { printf("A constructor param\n"); }
~A() { printf("A destructor\n");  }

void Print() { printf("This is A\n"); }

int m_a;
};

int _tmain(int argc, _TCHAR* argv[])
{
shared_ptr<A> d = make_shared<A>();
shared_ptr<A> e = make_shared<A>(1);
d->Print();
e->Print();
getchar();
return 0;
}


运行结果:

A constructor
A constructor param
This is A
This is A


Q: 为什么要尽量使用 make_shared()?

A: 为了节省一次内存分配,原来 shared_ptr<A> x(new A); 需要为 A 和 ref_count 各分配一次内存,现在用 make_shared() 的话,可以一次分配一块足够大的内存,供 A 和 ref_count 对象容身。不过 A 的构造函数参数要传给 make_shared(),后者再传给 A::A()。

shared_ptr有两种类型转换函数,一个是static_pointer_cast, 一个是dynamic_pointer_cast,用法和static_cast和dynamic_cast很像。

看如下例子:

#include <stdio.h>
#include <memory>
using namespace std;

class A
{
public:
A() { printf("A constructor\n"); }
~A() { printf("A destructor\n"); }

virtual void VFun() {}
};

class B: public A
{
public:
B() { printf("B constructor\n"); }
~B() { printf("B destructor\n"); }

void VFun() {}
};

int _tmain(int argc, _TCHAR* argv[])
{
shared_ptr<A> a = shared_ptr<B>(new B());
printf("a.get(): %p\n\n", a.get());
shared_ptr<B> b = dynamic_pointer_cast<B>(shared_ptr<A>(new A()));
printf("b.get(): %p\n\n", b.get());
shared_ptr<B> c = dynamic_pointer_cast<B>(a);
printf("c.get(): %p\n\n", c.get());
getchar();
return 0;
}

运行结果如下:
A constructor
B constructor
a.get(): 0066AEE8

A constructor
A destructor
b.get(): 00000000

c.get(): 0066AEE8
dynamic_pointer_cast下行转换基类必须有虚函数成员

#include <stdio.h>
#include <memory>
using namespace std;

class A
{
public:
A() { printf("A constructor\n"); }
~A() { printf("A destructor\n"); }
};

class B: public A
{
public:
B() { printf("B constructor\n"); }
~B() { printf("B destructor\n"); }
};

int _tmain(int argc, _TCHAR* argv[])
{
shared_ptr<B> b = static_pointer_cast<B>(shared_ptr<A>(new A()));
printf("b.get(): %p\n", b.get());
b.reset();
printf("\n");
shared_ptr<A> a = static_pointer_cast<A>(shared_ptr<B>(new B()));
printf("a.get(): %p\n", a.get());
a.reset();
getchar();
return 0;
}

运行结果如下:
A constructor
b.get(): 0049AEE8
A destructor

A constructor
B constructor
a.get(): 0049AEE8
B destructor
A destructor
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: