将 STL(c++11) 与 WinAPI 相结合
Combining STL(c++11) with WinAPI
我正在尝试使用 CreateThread 启动一个新线程并将 shared_pointer 的指针作为参数传递。如果我要使用良好的旧 ATL,它会调用 Ccomptr 的运算符 () 并增加引用计数并最终检索指针。
我正在尝试使用 STL 的 shared_ptr 做同样的事情,但我收到一个错误,其中 std::shared_ptr 到 LPVOID 之间的转换不存在。
std::shared_ptr<X> m_pSettings = std::make_shared(new ....);
if (nullptr == (m_hBackgroundThread = ::CreateThread(
nullptr, // default security attributes
0, // use default stack size
ThreadProc, // thread function name
m_pSettings, // argument to thread function
0, // use default creation flags
0)))
{
LOG_ERROR(L"Failed to create thread");
return false;
}
您可以像这样通过指针传递 shared_ptr 对象:&m_pSettings
然后在您的 ThreadProc
中取消引用它:
std::shared_ptr<X> pSettings = *static_cast<std::shared_ptr<X>*>(lpParam);
可能您需要先复制 shared_ptr
,然后再将指向它的指针传递给 CreateTrhead
,这样它将在范围内,而 ThreadProc
运行.
如您所知,正确答案是使用 std::thread
:
// Hey, look: No magic nullptrs and zeros nobody ever changes to non-defaults anyway!
std::thread t(ThreadProc, m_pSettings);
// Don't forget to
t.detach();
// if you let the std::thread object destruct without first joining it and making sure
// the thread finishes executing
不仅 std::thread
解决了您的问题,它还有许多其他好处,例如允许您轻松传递多个参数,它 copies/moves/does-the-right-thing 与您传递的参数等,并且它不需要您求助于任何所谓的聪明但实际上不是黑客。如果您使用 std::async
而不是 std::thread
,您甚至可以在调用线程中获取导致线程函数展开的异常(如果有的话)。
传递 CreateThread
您的 shared_ptr
地址然后在 ThreadProc
中取消引用它的替代方法可能有效,如果您非常小心的话 - 至少你必须确保调用者的 shared_ptr
在 ThreadProc
完成之前不会消失 - 但这只是要求发生坏事。
当然,如果您别无选择,那就是您所做的,但是考虑到 std::thread
和朋友做任何其他事情都是错误的,而且是在浪费时间。
此外,您与 ATL 的比较似乎是建立在误解之上的。区别不在于 ATL 的智能指针非常聪明并且能够以某种神奇的方式保持引用计数,即使在为您提供原始指针时(尽管我不知道 CComPtr::operator()
),而 C++ 标准库智能指针是蹩脚的,不要那样做。区别在于管理自己的引用计数和管理自己的生命周期的特殊对象之间的区别,前提是您在使用它们时声明(即调用 AddRef
)和任意资源。
COM 的智能指针(无论是 CComPtr
或 _com_ptr_t
还是任何半生不熟的蹩脚 class 你在网上都可以)基本上是对 COM 对象固有能力的包装管理自己的生命周期。
您可以将 AddRed
、Release
等(显然具有相关语义)添加到 class X
中,并将其包装在一个 COM 智能指针...
我正在尝试使用 CreateThread 启动一个新线程并将 shared_pointer 的指针作为参数传递。如果我要使用良好的旧 ATL,它会调用 Ccomptr 的运算符 () 并增加引用计数并最终检索指针。
我正在尝试使用 STL 的 shared_ptr 做同样的事情,但我收到一个错误,其中 std::shared_ptr 到 LPVOID 之间的转换不存在。
std::shared_ptr<X> m_pSettings = std::make_shared(new ....);
if (nullptr == (m_hBackgroundThread = ::CreateThread(
nullptr, // default security attributes
0, // use default stack size
ThreadProc, // thread function name
m_pSettings, // argument to thread function
0, // use default creation flags
0)))
{
LOG_ERROR(L"Failed to create thread");
return false;
}
您可以像这样通过指针传递 shared_ptr 对象:&m_pSettings
然后在您的 ThreadProc
中取消引用它:
std::shared_ptr<X> pSettings = *static_cast<std::shared_ptr<X>*>(lpParam);
可能您需要先复制 shared_ptr
,然后再将指向它的指针传递给 CreateTrhead
,这样它将在范围内,而 ThreadProc
运行.
如您所知,正确答案是使用 std::thread
:
// Hey, look: No magic nullptrs and zeros nobody ever changes to non-defaults anyway!
std::thread t(ThreadProc, m_pSettings);
// Don't forget to
t.detach();
// if you let the std::thread object destruct without first joining it and making sure
// the thread finishes executing
不仅 std::thread
解决了您的问题,它还有许多其他好处,例如允许您轻松传递多个参数,它 copies/moves/does-the-right-thing 与您传递的参数等,并且它不需要您求助于任何所谓的聪明但实际上不是黑客。如果您使用 std::async
而不是 std::thread
,您甚至可以在调用线程中获取导致线程函数展开的异常(如果有的话)。
传递 CreateThread
您的 shared_ptr
地址然后在 ThreadProc
中取消引用它的替代方法可能有效,如果您非常小心的话 - 至少你必须确保调用者的 shared_ptr
在 ThreadProc
完成之前不会消失 - 但这只是要求发生坏事。
当然,如果您别无选择,那就是您所做的,但是考虑到 std::thread
和朋友做任何其他事情都是错误的,而且是在浪费时间。
此外,您与 ATL 的比较似乎是建立在误解之上的。区别不在于 ATL 的智能指针非常聪明并且能够以某种神奇的方式保持引用计数,即使在为您提供原始指针时(尽管我不知道 CComPtr::operator()
),而 C++ 标准库智能指针是蹩脚的,不要那样做。区别在于管理自己的引用计数和管理自己的生命周期的特殊对象之间的区别,前提是您在使用它们时声明(即调用 AddRef
)和任意资源。
COM 的智能指针(无论是 CComPtr
或 _com_ptr_t
还是任何半生不熟的蹩脚 class 你在网上都可以)基本上是对 COM 对象固有能力的包装管理自己的生命周期。
您可以将 AddRed
、Release
等(显然具有相关语义)添加到 class X
中,并将其包装在一个 COM 智能指针...