std :: unique_ptr和指向指针的指针

时间:2010-12-19 20:36:10

标签: com c++11

我一直在使用std :: unique_ptr存储一些COM资源,并提供了自定义删除功能。但是,许多COM函数都需要指向指针的指针。现在,我在我的编译器中使用_Myptr的实现细节。它会打破unique_ptr直接访问这个数据成员,还是应该存储一个gajillion临时指针来构造来自?

的unique_ptr rvalues?

4 个答案:

答案 0 :(得分:6)

COM对象的性质是引用可计数的,所以你不应该使用除ATL::CComPtr_com_ptr_t之类的引用计数智能指针之外的任何东西,即使它似乎不适合你的用例(我完全理解)你的顾虑,我只是觉得你给他们分配了太多的重量)。这两个类都设计用于在使用COM对象时出现的所有有效场景,包括获取指向指针的指针。是的,这有点太多的功能,但如果你不期望任何特定的负面后果你不能容忍你应该只使用这些类 - 它们的设计正是为了这个目的。

答案 1 :(得分:4)

不久前我不得不解决同样的问题,我提出了两种不同的解决方案:

第一个是一个简单的包装器,它封装了一个'可写“指针,可以std::move进入我的智能指针。使用您提到的临时指针只是更方便,因为您无法直接在调用站点定义类型。

因此,我没有坚持这一点。所以我所做的是一个Retrieve辅助函数,它将获得COM函数并返回我的智能指针(并在内部执行所有临时指针内容)。现在这简单地适用于只有一个T**参数的自由函数。如果你想在更复杂的事情上使用它,你可以通过std::bind传递呼叫,只留下指针返回空闲。

我知道这不是你所要求的,但我认为这是解决你所遇问题的一个简洁方法。

作为旁注,我更喜欢boost的intrusive_ptr而不是std :: unique_ptr,但这是一个品味问题,一如既往。

编辑:以下是使用boost :: intrusive_ptr从我的版本传输的一些示例代码(因此它可能无法与unique_ptr一起使用)

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生成的仿函数应该具有签名typedef来派生指针类型。如果您遇到错误的HRESULT,则可以抛出异常。

答案 2 :(得分:1)

C ++ 0x智能指针有一种可移植的方式来获取原始指针容器.get()或完全使用.release()释放它。你也可以随时使用&amp;(* 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是一个单独的问题,尖锐的可能是正确的。

答案 3 :(得分:-1)

使用这样的辅助函数。

template< 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;
}