我想std::shared_ptr
在调用其他窗口或线程时升级我的MFC生产代码以使用智能指针.这样的呼叫是SendMessage
,PostMessage
并且PostThreadMessage
通过wparam
和lparam
分别是unsigned int
和long
.目前,我创建了一个类对象,一个新的对象,使调用传递一个指向该对象的指针,使用接收端的对象然后删除它.
由于shared_ptr
我的其余代码工作得很好,我想至少探讨为什么我不能对Windows调用做同样的事情.
目前的电话:
auto myParams = new MyParams(value1, value2, value3); PostThreadMessage(MSG_ID, 0, reinterpret_cast< LPARAM >( myParams ); ReceivingMethod::OnMsgId( WPARAM wParam, LPARAM lParam) { auto myParams = reinterpret_cast< MyParams * >( lParam ); ... // use object delete myParams; }
到类似C++ 11的智能指针调用:
std::shared_ptr< MyParams > myParams( new MyParams( value1, value2, value3 ) ); PostThreadMessage( MSG_ID, 0, ???myParams??? ); ReceivingMethod::OnMsgId( WPARAM wParam, LPARAM lParam ) { auto myParams = ???lParam???; ... // use object }
编辑1:
@Remy Lebeau:以下是使用unique_ptr传递方法修改的示例代码,但是,在传递对象时,代码中存在泄漏:
struct Logger { Logger() { errorLogger = ( ErrorLogger * )AfxBeginThread( RUNTIME_CLASS( ErrorLogger ), THREAD_PRIORITY_BELOW_NORMAL ); } ~Logger() { // gets properly dtor'ed upon app exit } void MakeLogMsg( ... ); ErrorLogger * errorLogger; std::unique_ptr< LogParams > logParams; }; Logger logger; std::recursive_mutex logParamsRecursiveMu; // because of multiple requests to lock from same thread struct ErrorLogger : public CWinThread { ErrorLogger() { } ~ErrorLogger() { // gets properly dtor'ed before logger upon app exit } afx_msg void OnLog( WPARAM wParam, LPARAM lParam ); }; void Logger::MakeLogMsg( ... ) { // construct msg from logparams // make msg smart object using unique ptr and send to errorlogger thread queue logParams = std::make_unique< LogParams >(); // set logparams // with the addition of the mutex guard, the leaks are gone logParamsRecursiveMu.lock(); logger.errorLogger->PostThreadMessage( ONLOG_MSG, 0, reinterpret_cast< LPARAM >( logParams.get() ) ); logParams.release(); // no longer owns object logParamsRecursiveMu.unlock(); } void ErrorLogger::OnLog( WPARAM wParam, LPARAM lParam ) { std::unique_ptr< LogParams > logParams( reinterpret_cast< LogParams * >( lParam ) ); }
请注意,当我注释掉unique_ptr的传递时,泄漏消失了.我的代码与使用此方法的代码有何不同?
EDIT2:
关于@Remy Lebeau
如何std::unique_ptr
使用代替的答案std::shared_ptr
,我在下面的评论中说,"......没有额外的对象可以实现.没有明显的缺点." 嗯,这不是真的.该MyParams
对象具有用于每个不同类型的消息被创建.有些应用可能只有几种类型,但有些可能有100种或更多.每次我想在另一边执行一个函数时,我必须创建一个新结构,它有一个构造函数,它接受目标调用的所有参数.如果有很多,实施起来非常繁琐,难以维护.
我认为仅通过传递参数就可以消除结构构建阶段.
显然有新的C++ 1x结构可以帮助实现这一目标.其中一个可能std::forward_as_tuple
就是"构造一个对args中参数的引用元组,这些参数适合作为函数的参数转发".
对于我的应用程序,我通过模板化解决了问题MyParams
,但对于任何想要避免添加大量结构的人,他可能想要使用元组之类的东西.
编辑3:@ RemyLebeau的答案号1和@ rtischer8277的答案号5都是正确的.不幸的是,StackOverflow无法识别多个正确的答案.这个StackOverflow限制反映了一种有缺陷的心理语言学假设,即语言语境对于同一语言组是普遍的,而事实并非如此.(参见Roger Harris关于固定代码语言神话的"整合语言学概论",第34页).为了回应我原来的帖子,@ RemyLebeau根据显示new
ed 的发布代码所描述的上下文回答了这个问题MyParams
(参见编辑2:更多解释).很久以后在答案5(rtischer8277)中,我根据问题的原始措辞回答了这个问题,该问题询问是否std::shared_ptr
可以跨线程使用PostThreadMessage
.作为一个合理的结果,我已经将正确答案重新分配给@RemyLebeau,这是第一个正确的答案.
编辑4:我在这篇文章中添加了第三个合法答案.见第6 回答开头@Remy勒博和@ rtischer8277迄今已提交了两个答案我原来的帖子....此解决方案的作用是将跨线程访问转换为概念上简单的RPC(远程过程调用).虽然本答案显示了如何使用a future
来控制所有权和同步,但它没有说明如何创建具有任意数量参数的消息对象,这些参数可以安全地在PostThreadMessage调用的任一侧使用.该功能在StackOverflow上的解决答案发出传递参数包在使用forward_as_tuple遗留函数签名.