智能指针作为函数参数:普通参数、指针参数、WPARAM

一、auto_ptr和shared_ptr作为普通参数、指针参数

        我想这是我们使用最多的,直接传过去好了,基本上没什么好担心的。例如:

        1.

        T* pt = new T;     
      auto_ptr ap( pt);

        // void f1(auto_ptr ap);

        f1(ap);

        //  ap 为 empty(空)了


        // void f2(T* pt);

        f2(ap.get()); 

        //  ap还拥有所有权。

       唯一要注意的是,auto_ptr是独占的,一旦赋值给别人后,就把所有权也交给别人了,自己就是一个空指针了,不能再使用了。详细请看stl文档或stl标准程序库。


        2.

        shared_ptr sp(new T);

        // void f1(shared_ptr sp);

        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 shPtr = shared_from_this();
            boost::weak_ptr wPtr=shPtr;
            _beginthreadex( NULL, 0, &test::threadRun, &wPtr, 0, &threadID );
            ...
        }


        /*this is a static function*/
        UINT __stdcall test::threadRun( LPVOID lpParam )
        { 
                shared_ptr k      = static_cast< boost::weak_ptr* >(lpParam)->lock();
             ...
        }

       使用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,得到其所有权。


你可能感兴趣的:(C++,VC)