shared_ptr的用法

先看一个例子:

#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




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值