Thursday, October 6, 2011

all smart ptr's should have a replace method

A lot of C++ code ends up interfacing with C functions. std::vector and std::basic_string have been constructed to make it possible to use them with c functions (basic_string::c_str vector::data and vector::operator[])

Smart pointers, however do not interface well with c code. I believe that c function interfacing is unsupported due to concern that address() is too dangerous to expose. While interfacing with c code does require the same return value that address would return, it does not require the same semantics.

The implementation of replace() would call reset() and then return address(). This would mean that the user could not accidentally leak a pointer by using replace()

Here is some code that shows how std::unique_ptr interacts with a c function now and how it would work if it had replace().

struct CoTask_deleter {
  void operator()(void* expired) {
    CoTaskMemFree(expired);
  }
};

unique_hresult hresult;

{
  //
  // without replace
  //
  LPOLESTR rawString = nullptr;
  std::unique_ptr<OLECHAR, CoTask_deleter> string;
  hresult.reset(StringFromCLSID(GUID_NULL, &rawString));
  // memory allocation is not 'owned'
  // any mistake from here through the
  // unique_ptr reset will result in a
  // leak
  if (hresult.ok()) {
    string.reset(raw_string);
    raw_string = nullptr;
    // now the memory is safely owned
  }
}

{
  //
  // with replace
  //
  std::unique_ptr<OLECHAR, CoTask_deleter> string;
  hresult.reset(
    StringFromCLSID(
        GUID_NULL,
        string.replace()));
  // there is no point when the memory is not owned
}

if (!hresult)
{
  return;
}

No comments:

Post a Comment