unique_ptr 双指针处理
unique_ptr handling for double pointer
我正在使用具有如下签名的 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
显然我可以为此写一个小的 class,但我想知道是否有现有的实用程序已经为此提供了。
事实证明,std::unique_ptr
无法做到这一点。从此 class 获取指针的唯一方法是:
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);
我正在使用具有如下签名的 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
显然我可以为此写一个小的 class,但我想知道是否有现有的实用程序已经为此提供了。
事实证明,std::unique_ptr
无法做到这一点。从此 class 获取指针的唯一方法是:
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);