下面的知识只是为了解决这个问题:
class Hello
{
public:
void run(int c)
{ do_sth(c); }
};
Hello* h = new Hello;
Task* t = Bind(&Hello::run,h); 将类指针及类成员函数封装到一个Task类中
thread->PostTask(t); 将Task投递到线程
问题在:投递线程之后,如果h被delete了,此时线程去执行t的时候就会出错,因为h被删除了。
我的期望:在执行t的时候,先检查h是否还存在,不存在则丢弃该Task。
c++中有一个weak_ptr,弱指针。我知道这个可以解决这个问题,但是如何解决?
1. weak_ptr对象的创建和值
(1).直接创建weak_ptr 对象是可以的,但是它的值是 empty
weak_ptr<int> tem1; //可以创建weak_ptr的对象,但是它的值是empty
(2).只能用 make_shared函数 或者 shared_ptr 指针初始化 weak_ptr 对象,只有这样weak_ptr 才会有值
weak_ptr<int> tem1 = make_shared<int>();
shared_ptr<int> sharedPtr(new int);
weak_ptr<int> tem3(sharedPtr);
(3).下面的做法是错误的,编译通不过
weak_ptr<int> tem(new int);
(4).把weak_ptr提升为 shared_ptr
如果weak_ptr是empty,那么下面的代码会抛出异常 :bad_weak_ptr
weak_ptr<int> tem1;
shared_ptr<int> sharedPtr(tem1); // 在执行的时候会抛出异常
2.enable_shared_from_this的说明
(1)enable_shared_from_this类的主要内容
template<class _Ty> class enable_shared_from_this
{
public:
shared_ptr<_Ty> shared_from_this()
{ // return shared_ptr
return (shared_ptr<_Ty>(_Wptr));
}
private:
mutable weak_ptr<_Ty> _Wptr;
}
(2).enable_shared_from_this这个类的主要作用是作为一个类的基类,并且派生类唯一能用上的函数就是 shared_from_this()。
在上面列出的源码里面没有说明 _Wptr 是怎样被赋值的。下面就给出 _Wptr 被赋值的过程:(注意,在vs源码里面没有看到整个过程,因为vs封装了)
class S:public able_shared_from_this<S>{};
Rule: when a class inherits from enable_shared_from_this, it almost always means it should work with shared_ptr together.
What happened behind the scene for shared_ptr<S> p(new S) ?
(1) enable_shared_from_this construct is called
(2) S constructor is called
(3) shared_ptr constructor is called (the magic happens here)
|
| -> __enable_shared_from_this_helper is called in shared_ptr constructor
|
|-> enable_shared_from_this::_M_weak_assign is called
|
|-> weak_ptr<_Tp>::._M_assign(__p, __n);
(called on mutable enable_shared_from_this::_M_weak_this instance in
struct S object. This calls sets (inits) the weak_ptr in struct S object)
|
|-> Set weak_ptr<_Tp>::_M_ptr and
weak_ptr<_Tp>:: _M_refcount (__weak_count<_Lp>)
从上面的赋值过程可以看出,如果只是定义一个 S 的对象,那么就不会涉及到 shared_ptr ,所以在调用 shared_from_this() 这个函数的时候,因为 _Wptr 是empty,所以会抛出异常。
3.具备了 weak_ptr 和 enable_shared_from_this 知识后就可以解决上面的问题了:
解决问题的核心是:保存一个weak_ptr对象,这个weak_ptr对象是 shared_ptr的 observer,并且weak_ptr不能提升为 shared_ptr的话 就可以用下面的判断语句。
class Hello:public enable_shared_from_this<Hello>
{
public:
void run()
{
std::cout<<"run" <<std::endl;
}
};
class Thread
{
public:
Thread(shared_ptr<Hello> SPtr):_WPtr(SPtr){}
void task(boost::function<void()>)
{
shared_ptr<Hello> SPtr;
SPtr = _WPtr.lock();
if (!SPtr) //如果 weak_ptr 不能提升为 shared_ptr 那么说明这个对象已经不存在了。
{
std::cout<<"the hello is not exist"<<std::endl;
return;
}
SPtr->run();
}
private:
weak_ptr<Hello> _WPtr;
};
void main()
{
shared_ptr<Hello> sharedHello(new Hello);
boost::function<void()> f1;
f1 = boost::bind(&Hello::run, sharedHello);
Thread myThread(sharedHello);
myThread.task(f1);
}