I'm trying to use boost::multi_array_ref to use a block of contiguous data in my code. But I worry about if I use the code like below, the 1d C array won't be confirmed to save:
#include <iostream>
#include "boost/multi_array.hpp"
boost::multi_array_ptr<double, 2> test(int N,int c,int d) {
double *data = new double[N];
boost::multi_array_ref<double, 2> a(data, boost::extents[c][d]);
for (int i = 0; i < 10; i ) {
for (int j = 0; j < 10; j ) {
a[i][j] = 10 * i j;
}
}
return a;
}
int main()
{
boost::multi_array_ptr<double, 2> a = test(100000000,10000,10000);
for (int i = 0; i < 10; i ) {
for (int j = 0; j < 10; j ) {
std::cout << a[i][j] << std::endl;
}
}
}
The result is right and I want to use std::unique_ptr
to replace the C style array, but the Visual Studio told me:
no instance of constructor "boost::multi_array_ref<T, NumDims>::multi_array_ref [with T=double, NumDims=2Ui64]" matches the argument list
I don't know which kind of parameter boost::multi_array_ref need. Why the std::unique_ptr
can't be use as parameter but C style array can? Can I use C style array without worry? Is safe boost::multi_array_ref returned by a function?
I'm sure that it will cause memory leak,but how to solve it?
CodePudding user response:
double *data = new double[N];
That's a raw pointer and no-one owns the allocation. You're correct that it leads to memory leaks. However, since you want to include ownership, why use multi_array
_ref
?
#include <algorithm>
#include <numeric>
#include "boost/multi_array.hpp"
auto test(int c, int d) {
boost::multi_array<double, 2> a(boost::extents[c][d]);
std::iota(a.data(), a.data() a.num_elements(), 0);
return a;
}
#include <fmt/ranges.h>
int main()
{
boost::multi_array<double, 2> a = test(4, 5);
fmt::print("{}\n", a);
fmt::print("{}\n", test(3, 6));
fmt::print("{}\n", test(6, 2));
}
Prints:
[[0, 1, 2, 3, 4], [5, 6, 7, 8, 9], [10, 11, 12, 13, 14], [15, 16, 17, 18, 19]]
[[0, 1, 2, 3, 4, 5], [6, 7, 8, 9, 10, 11], [12, 13, 14, 15, 16, 17]]
[[0, 1], [2, 3], [4, 5], [6, 7], [8, 9], [10, 11]]
And has no memory leaks.
If you need the multi-array-ref:
You might hack your way around with owning smart pointers:
using ARef = boost::multi_array_ref<double, 2>;
using ARefPtr = boost::shared_ptr<ARef>;
Now you can allocate the data like you did before - but without the leak:
auto test(int c, int d) {
auto data = boost::shared_ptr<double[]>(new double[c*d]);
See this post for details and compatibility with
std::shared_ptr
And Use the aliasing constructor to share ownership of data while changing the apparent element type to ARef:
auto a = ARefPtr(data, new ARef(data.get(), boost::extents[c][d]));
std::iota(a->data(), a->data() a->num_elements(), 0);
return a;
}
#include <fmt/ranges.h>
int main()
{
ARefPtr a = test(4, 5);
fmt::print("{}\n", *a);
fmt::print("{}\n", *test(3, 6));
fmt::print("{}\n", *test(6, 2));
}
Of course, now you're dealing with smart pointers, so you need more de-references. See it Live:
[[0, 1, 2, 3, 4], [5, 6, 7, 8, 9], [10, 11, 12, 13, 14], [15, 16, 17, 18, 19]]
[[0, 1, 2, 3, 4, 5], [6, 7, 8, 9, 10, 11], [12, 13, 14, 15, 16, 17]]
[[0, 1], [2, 3], [4, 5], [6, 7], [8, 9], [10, 11]]
CodePudding user response:
I have found a perfect solution for me without boost.
A self-defined 2d array(Matrix) class
But if someone can give an answer about boost::multi_array_ref, please delete this answer.