【问题标题】:unique_ptr handling for double pointer双指针的unique_ptr处理
【发布时间】:2016-03-11 06:22:56
【问题描述】:

我正在使用具有如下签名的 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);

我可以用std::unique_ptr 结束my_array 以便自动调用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

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

【问题讨论】:

  • 可以,但为什么不简单地使用矢量?
  • 他可能使用的是旧版 C 代码。如上所示,它需要一个double 双指针。
  • @H.Guijt C 函数不使用向量方法,所以我不知道它是如何工作的。我无法更改 C 函数。
  • 对于谁关闭了我的问题作为重复,请解释它是如何相同的。我的函数没有返回指针。
  • @beldaz The closeer 断言std::unique_ptr&lt;double, decltype(std::free) *&gt; a_free { my_array, std::free };load_arraycall 之后将适用于您的情况。

标签: c++ unique-ptr


【解决方案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);

【讨论】:

  • 您可以将其包装在一个函数中,而不是使用一个块,它可能会返回unique_ptr 和大小,并将source 作为参数
  • 即使使用这种解决方案,您也必须将长度单独携带到指针上,这并不理想;要考虑的一种方法是创建一个包含指针和长度的自定义类(并且不可复制并在其析构函数中调用free,您可以提供容器适配器)
  • @MM 谢谢。我进一步采纳了您的建议,并用一个修改 unique_ptr 并返回长度的新函数进行了总结。
猜你喜欢
  • 1970-01-01
  • 2022-01-17
  • 1970-01-01
  • 2014-05-25
  • 1970-01-01
  • 2021-01-06
  • 1970-01-01
  • 2021-10-27
  • 2014-06-05
相关资源
最近更新 更多