我一直在使用std::unique_ptr存储一些COM资源,并提供了自定义的删除函数。然而,许多COM函数需要指向指针的指针。目前,我正在使用编译器中的_Myptr实现细节。如果直接访问这个数据成员,会破坏unique_ptr吗?或者我应该存储大量临时指针来构造unique_ptr rvalues?
COM对象天生就可以通过引用计数来管理,因此在任何情况下都不应该使用除了引用计数智能指针之外的任何东西,如ATL::CComPtr
或_com_ptr_t
,即使对于您的用例似乎不合适(我完全理解您的担忧,但我认为您赋予它们过多的重量)。这两个类旨在在使用COM对象时涉及所有有效场景,包括获取指向指针的指针。是的,这有点太多功能了,但如果您不期望任何特定的负面后果,您应该只使用这些类 - 它们恰好为此目的而设计。
template <class T, class PtrType, class PtrDel>
HRESULT retrieve(T func, std::unique_ptr<PtrType, PtrDel>& ptr)
{
ElementType* raw_ptr=nullptr;
HRESULT result = func(&raw_ptr);
ptr.reset(raw_ptr);
return result;
}
std::unique_ptr<IFileDialog, ComDeleter> FileDialog;
/*...*/
using std::bind;
using namespace std::placeholders;
std::unique_ptr<IShellItem, ComDeleter> ShellItem;
HRESULT status = retrieve(bind(&IFileDialog::GetResult, FileDialog, _1), ShellItem);
为了加分,您甚至可以让retrieve
返回unique_ptr而不是通过引用获取它。 bind
生成的函数对象应该具有typedefs签名以派生指针类型。如果出现错误的HRESULT
,则可以抛出异常。
C++0x智能指针有一种可移植的方法来获取原始指针容器.get()或完全释放它.release()。您也可以始终使用&(*ptr),但这不太惯用。
如果您想使用智能指针来管理对象的生命周期,但仍需要原始指针来使用不支持智能指针的库(包括标准c库),则可以使用这些函数最方便地获取原始指针。
请记住,您仍然需要在您希望对象存在的时间内保留智能指针(因此要注意其生命周期)。
类似于:
call_com_function( &my_uniq_ptr.get() ); // will work fine
return &my_localscope_uniq_ptr.get(); // will not
return &my_member_uniq_ptr.get(); // might, if *this will be around for the duration, etc..
注意:这只是对你问题的一般回答。如何最好地使用COM是一个单独的问题,Sharptooth可能是正确的。
unique_ptr
内部指针的指针,而不仅仅是值。 - Puppytemplate< class T >
T*& getPointerRef ( std::unique_ptr<T> & ptr )
{
struct Twin : public std::unique_ptr<T>::_Mybase {};
Twin * twin = (Twin*)( &ptr );
return twin->_Myptr;
}
检查实现
int wmain ( int argc, wchar_t argv[] )
{
std::unique_ptr<char> charPtr ( new char[25] );
delete getPointerRef(charPtr);
getPointerRef(charPtr) = 0;
return charPtr.get() != 0;
}
new[]
。 - Puppy
ATL::CComPtr
或_com_ptr_t
? - sharptooth