我正在使用具有以下签名的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_array
与std::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
显然我可以为此编写一个小类,但我对是否已经提供此功能的现有实用程序感兴趣。
答案 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);