函数返回安全 boost::multi_array_ref 吗?
Is safe boost::multi_array_ref returned by a function?
我正在尝试使用 boost::multi_array_ref 在我的代码中使用连续数据块。但是我担心如果我使用下面的代码,一维C数组将不会被确认保存:
#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;
}
}
}
结果是对的,我想用std::unique_ptr
代替C风格数组,但是Visual Studio告诉我:
no instance of constructor "boost::multi_array_ref<T, NumDims>::multi_array_ref [with T=double, NumDims=2Ui64]" matches the argument list
我不知道boost::multi_array_ref需要哪种参数。为什么 std::unique_ptr
不能用作参数但 C 样式数组可以?我可以放心地使用 C 样式数组吗?函数返回的 boost::multi_array_ref 安全吗?
我确定会导致内存泄漏,但是如何解决呢?
我找到了一个完美的解决方案 without boost。
一个self-defined二维数组(矩阵)class
有boost的方案是sehe的答案
double *data = new double[N];
这是一个原始指针,no-one 拥有分配。你是正确的,它会导致内存泄漏。但是,既然要包含所有权,为什么还要用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));
}
打印:
[[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]]
并且没有内存泄漏。
如果您需要 multi-array-ref:
您可能会通过拥有智能指针来解决问题:
using ARef = boost::multi_array_ref<double, 2>;
using ARefPtr = boost::shared_ptr<ARef>;
现在您可以像以前一样分配数据 - 但没有泄漏:
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
并使用别名构造函数在更改时共享数据所有权
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));
}
当然,现在你处理的是智能指针,所以你需要更多de-references。看到了吧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]]
我正在尝试使用 boost::multi_array_ref 在我的代码中使用连续数据块。但是我担心如果我使用下面的代码,一维C数组将不会被确认保存:
#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;
}
}
}
结果是对的,我想用std::unique_ptr
代替C风格数组,但是Visual Studio告诉我:
no instance of constructor "boost::multi_array_ref<T, NumDims>::multi_array_ref [with T=double, NumDims=2Ui64]" matches the argument list
我不知道boost::multi_array_ref需要哪种参数。为什么 std::unique_ptr
不能用作参数但 C 样式数组可以?我可以放心地使用 C 样式数组吗?函数返回的 boost::multi_array_ref 安全吗?
我确定会导致内存泄漏,但是如何解决呢?
我找到了一个完美的解决方案 without boost。
一个self-defined二维数组(矩阵)class
有boost的方案是sehe的答案
double *data = new double[N];
这是一个原始指针,no-one 拥有分配。你是正确的,它会导致内存泄漏。但是,既然要包含所有权,为什么还要用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));
}
打印:
[[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]]
并且没有内存泄漏。
如果您需要 multi-array-ref:
您可能会通过拥有智能指针来解决问题:
using ARef = boost::multi_array_ref<double, 2>;
using ARefPtr = boost::shared_ptr<ARef>;
现在您可以像以前一样分配数据 - 但没有泄漏:
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
并使用别名构造函数在更改时共享数据所有权 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));
}
当然,现在你处理的是智能指针,所以你需要更多de-references。看到了吧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]]