unique_ptr处理双指针

时间:2016-03-11 06:22:57

标签: c++ unique-ptr

我正在使用具有以下签名的C函数:

/**
 * Read values from source file and store in a newly 
 * allocated array
 */
size_t load_array(FILE * source, double ** pdest) {
  size_t values_read;
  double * dest;
  // ...
  // Keep reading in values from source, incrementing values_read
  // resizing dest when needed.
  // ...
  *pdest = dest;
  return values_read;
}

目前在我的C ++代码中被调用,如下所示:

double * my_array;
size_t array_length = load_array(source, &my_array);
// ... do stuff with my_array ...
free(my_array);

我可以将my_arraystd::unique_ptr打包在一起,以便自动调用free吗?我无法更改C函数(它是外部库的一部分),因此我无法更改其中使用的数据结构。

similar question on SO,但在该问题中,C函数返回了一个指针,并且围绕此返回值创建了unique_ptr。如果首先创建一个哑指针然后再包装,那么一些建议的答案就会起作用,例如:

double * my_array;
size_t array_length = load_array(source, &my_array);
auto my_array_wrapper = std::unique_ptr<double, decltype(free)*>{ my_array, free };
// ... do stuff with my_array_wrapper ...

// free() called on wrapped pointer when my_array_wrapper goes out of scope

这对我来说似乎不太干净,因为我的代码中仍然会有原始指针。我想做什么来完全包含指针,例如:

clever_ptr my_clever_array;
size_t array_length = load_array(source, my_clever_array.get_ptr_address());
// ... do stuff with my_clever_array ...

// free() called on wrapped pointer when wrapper goes out of scope

显然我可以为此编写一个小类,但我对是否已经提供此功能的现有实用程序感兴趣。

1 个答案:

答案 0 :(得分:1)

事实证明,std::unique_ptr无法做到这一点。获取此类指针的唯一方法是:

  • pointer get() const noexcept;const,不允许托管指针的值发生变化(返回的指针不是const,但它是一个副本管理一个,因此更改它的值不会更改unique_ptr
  • 中的值
  • pointer release() noexcept;会释放托管指针的所有权,因此当它超出范围时不会调用free

因此唯一的路径是在更新指针后将其包起来。为避免指针位于其周围,可将其置于一个块中以限制其范围:

std::unique_ptr<double, decltype(free)*> my_array_wrapper{nullptr, free};
{
  double * my_array;
  size_t array_length = load_array(source, &my_array);
  my_array_wrapper = std::unique_ptr<double, decltype(free)*>{ my_array, free };
}
// ... do stuff with my_array_wrapper ...
// free() called on wrapped pointer when wrapper goes out of scope

这可能会使用load_array函数的包装器进行扩展:

size_t load_array_wrapped(FILE * source, std::unique_ptr<double, decltype(free)*> & array_wrapper) {
  double * my_array;
  size_t array_length = load_array(source, &my_array);
  my_array_wrapper = std::unique_ptr<double, decltype(free)*>{ my_array, free };
  return array_length;
}

然后拨打:

std::unique_ptr<double, decltype(free)*> my_array_wrapper{nullptr, free};
size_t array_length = load_array_wrapped(source, my_array_wrapper);