unique_ptr
我最喜欢的一个方面是它提供的自动内存管理。我想将unique_ptr
与GSL向量一起使用。
但是,gsl_vector
有自己的释放内存机制(gsl_vector_free
)。有没有办法强制唯一指针使用GSL的向量释放方法? Valgrind(正确)报告在下面创建unique_ptr<gsl_vector>
时使用malloc / delete不匹配:
#include <memory>
#include <gsl/gsl_vector.h>
void mem_gsl() {
gsl_vector *vec;
vec = gsl_vector_calloc(2);
gsl_vector_set(vec, 0, 2.0);
printf("%f\n", gsl_vector_get(vec, 0));
gsl_vector_free(vec); // Without this, there is a memory leak.
}
void mem_unique_ptr() {
std::unique_ptr<gsl_vector> vec;
vec.reset(gsl_vector_calloc(2));
// Using .get() each time I want to use the gsl_vector seems like overhead.
gsl_vector_set(vec.get(), 0, 2.0);
printf("%f\n", gsl_vector_get(vec.get(), 0));
// Valgrind correctly reports a mismatched use of delete and free.
}
int main(int argc, char *argv[]) {
mem_gsl();
mem_unique_ptr();
return 0;
}
此外,每次我想访问vector元素时都必须调用get()
似乎相当乏味。有办法解决这个问题吗?
答案 0 :(得分:4)
您可以通过向std::unique_ptr
提供自定义删除工具来实现此目的。这样的事情可能会这样:
auto del = [](gsl_vector* p) { gsl_vector_free(p); };
std::unique_ptr<gsl_vector, decltype(del)> vec(gsl_vector_calloc(2), del);
答案 1 :(得分:2)
拥有make_unique gsl_vector和自定义删除器:
#include <memory>
// Fake gsl
typedef int gsl_vector;
gsl_vector* gsl_vector_calloc(std::size_t) { return 0; }
void gsl_vector_free(gsl_vector*) {}
// Deleter
struct gsl_vector_deleter {
void operator () (gsl_vector* p) {
gsl_vector_free(p);
}
};
// Unique Pointer
typedef std::unique_ptr<gsl_vector, gsl_vector_deleter> unique_gsl_vector;
unique_gsl_vector make_unique_gsl_vector() {
return unique_gsl_vector(gsl_vector_calloc(2));
}
int main() {
make_unique_gsl_vector();
return 0;
}
答案 2 :(得分:2)
要避免.get()
调用以及与gsl_vector
中包含unique_ptr
相关联的其他样板文件,您可以创建一个小型RAII包装器。
namespace gsl {
class vector
{
std::unique_ptr<gsl_vector, decltype(&gsl_vector_free)> v_;
public:
explicit vector(std::size_t num)
: v_(gsl_vector_calloc(num), gsl_vector_free)
{}
double operator[](std::size_t idx) const
{
return gsl_vector_get(v_.get(), idx);
}
void set(std::size_t idx, double value)
{
gsl_vector_set(v_.get(), idx, value);
}
};
}
这不仅避免了样板,而且还允许您轻松扩展功能,例如,添加一个带std::initializer_list<double>
的构造函数,以便您可以在单个表达式中构造和初始化向量。