shared_ptr的用法
2016-05-11 18:59
281 查看
先看一个例子:
运行结果如下:
另一个例子:
运行结果如下:
注意:上面代码运行输出以上结果后,还会弹出错误异常窗口
可以看出,a和b都关联到了p上,并且a和b的引用计数也是单独算的,都是1,这就导致函数退出的时候把p指向的对象销毁了两次,导致错误发生。
接着看例子:
运行结果如下:
share_ptr的成员函数get可以获取传统的C指针,此时引用计数仍然是1,不要对获取到的传统c指针进行delete操作,否则会发生错误
接下来的例子:
运行结果如下:
调用reset后,a就不再跟之前绑定的指针有任何关系了(实际过程是a的内部成员变量_Ptr和_Rep都被置为0,通过创建临时变量再Swap),所以引用b和c的引用计数也都相应减1
make_shared的使用:
运行结果:
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
#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
相关文章推荐
- BZOJ 3223: Tyvj 1729 文艺平衡树
- svn
- C# 中的委托和事件
- swift 中showAlertTitle的使用
- HDU2149(巴什博弈Bash Game)
- Django登录、注册、退出
- 深入javascript
- iOS Ad hoc
- Android通用流行框架大全
- XStream4Java高级应用
- 【BZOJ-3631】松鼠的新家 树形DP?+ 倍增LCA + 打标记
- android Activity runOnUiThread() 方法使用
- Android 热修复Nuwa的原理及Gradle插件源码解析
- js 二维数组的深拷贝
- android学习之AIDL初探
- 记我的第一次继承spring和hibernate
- 如何判断一个js对象是否一个DOM对象
- Linux下的SVN服务器搭建
- 【BaiduMapSDK系列】baidumapsdk: Authentication Error errorcode: 230 uid: -1 appid -1 msg: APP Scode码校验失败
- Pragmatic Scala:Create Expressive, Concise, and Scalable Applications (读书笔记)