一、auto_ptr和shared_ptr作为普通参数、指针参数
我想这是我们使用最多的,直接传过去好了,基本上没什么好担心的。例如:
1.
T* pt = new T;
auto_ptr
// void f1(auto_ptr
f1(ap);
// ap 为 empty(空)了
// void f2(T* pt);
f2(ap.get());
// ap还拥有所有权。
唯一要注意的是,auto_ptr是独占的,一旦赋值给别人后,就把所有权也交给别人了,自己就是一个空指针了,不能再使用了。详细请看stl文档或stl标准程序库。
2.
shared_ptr
// void f1(shared_ptr
f1(sp);
// sp还可以继续使用,引用计数型
// void f2(T* pt);
f2(sp.get());
二、关于线程
auto_ptr的拥有权只有一份,所以不适合赋值给多个线程。shared_ptr是线程安全的,没有问题。
如果你用boost里面的线程,用boost::function函数对象用shared_ptr还是很简单的。
如果用_beginthreadex和UINT __stdcall threadRun(LPVOID lpParam),哥求你,放弃这种使用方式吧。我现在很不喜欢这种使用方式,太古板了。如果你要在这种方式下使用智能指针赋值给LPVOID,那使用就稍微麻烦一点。
auto_ptr就不讲了,因为所有权的问题不建议给赋值给线程参数,如果要使用,请借鉴后面赋值给WPARAM。
shared_ptr网上有一个思路是对的,但有严重缺陷的方式:http://stackoverflow.com/questions/5102038/how-can-i-pass-boostshared-ptr-as-a-pointer-to-a-windows-thread-function?rq=1
test::start()
{
....
shared_ptr
boost::weak_ptr
_beginthreadex( NULL, 0, &test::threadRun, &wPtr, 0, &threadID );
}
/*this is a static function*/
UINT __stdcall test::threadRun( LPVOID lpParam )
{
shared_ptr
...
}
使用boost::weak_ptr的思路是很正确的,但是这样传&wPtr是很有问题的。必须用其他方式包装或传递shared_ptr。
三、PostMessage中智能指针传给WPARAM
最近一个项目中,要把一个结构通过PostMessage传给界面线程。这个结构数据当然是临时生成的,我这个工作线程对界面线程一无所知,只能通过发消息通知,boost里面的回调函数和信号事件无效。因为有个使用别人的控件窗口只能界面线程调用才显示,我也是用boost里面函数和回调不显示郁闷了很久,后来排除一切不可能因素才认定是工作线程非界面线程原因。
直接使用new是一件很头疼的事,因为释放是一件很麻烦的事,基本上不能遵守谁申请谁释放,因为我只负责把数据产生出来交给调用者,调用者的情况完全不知。
shared_ptr用的多,那就还是用只能指针吧。shared_ptr方式,完全可以参考上面的“二、关于线程”,用boost::weak_ptr辅助。
当然我用了auto_ptr,因为我觉得auto_ptr更符合我这里使用情况,把所有权转交给别人,自己就不管了。而且还不需要辅助指针weak_ptr。
下面介绍使用方式:
发送者:
std::auto_ptr<T> apMessage(newT());
if (PostMessage(WM_SHOW_MESSAGE, (WPARAM)apMessage.get(), ID_***))
{
// 释放控制权
apMessage.release();
}
接收者:
std::auto_ptr<T> apShowMessage(reinterpret_cast<T*>(wParam));
唯一要注意的是,发送者要释放控制权,不然,接收者无法重新包装成auto_ptr,我刚开始犯过这样的错误。表面上好像成功了,但是由于发送者并没有释放控制权即所有权,所以接收者并不能使用新包装的auto_ptr(表面上可以得到指针,由于异步,发送者并没有转交所有权,PostMessage后就释放内存了,接收者得到的是一个野指针)。
所以需要发送者在发送成功后释放控制权,让接收者重新包装成auto_ptr,得到其所有权。