使用 reinterpret_cast将数据从 std::vector 重塑<double>为指定维度的双精度**
Reshaping data from a std::vector<double> into double** of specified dimensions using reinterpret_cast
我有一个包含M*N
值的std::vector<double>
,我想将其重塑为一个double**
,其行为类似于double[N][M]
多维数组。 这些起点和终点可能看起来很奇怪,但不幸的是,它们都是由外部库决定的,所以我对它们无能为力。我问这个问题是为了看看是否有办法完成此操作,而无需简单地手动复制所有数据。
我确实读过这个问题,答案很好,但它的起点略有不同——不是从std::vector<double>
到double**
,而是从double[]
到double[][]
。我试图了解那里发生了什么,并将相同的原则应用于我的情况,但我无法让我的代码工作。如何正确执行此操作?
const int M = 3;
const int N = 2;
std::vector<double> f = { 0, 1, 2, 3, 4, 5 };
double* f1d = f.data();
// compiles and doesn't crash
// but f2d seems to be unitialized (at least f2d[1][1] is garbage)
// also has the wrong type (double[][] rather than double**)
double (&f2d)[N][M] = reinterpret_cast<double (&)[N][M]>(f1d);
// segfaults when trying to access e.g. f2d[0][0]
double** f2d = reinterpret_cast<double**>(f1d);
最终,我需要将数据传递到一个采用double**
参数的方法中,因此以下内容必须编译和运行而不会出现问题:
#include <iostream>
#include <vector>
void test(int M, int N, double **arr) {
for (int i = 0; i < N; ++i) {
for (int j = 0; j < M; ++j) {
std::cout << arr[i][j] << " ";
}
std::cout << std::endl;
}
};
int main() {
const int M = 3;
const int N = 2;
std::vector<double> f = { 0, 1, 2, 3, 4, 5 };
// whatever I need to do here to get f2d
test(M, N, f2d);
return 0;
}
预期产出:
0 1 2
3 4 5
基于double**
的"数组"与实际的多维数组完全不同,即double[N][M]
.它具有完全不同的布局并存储不同的信息,因此如果不存储任何其他信息,您就不可能做您想做的事情。
基于double**
的"数组"的工作方式是两级结构,其中第一级是包含指向各种常规一维数组的指针的数组。连续的多维数组不能直接用作基于double**
的"数组",因为带有指针的第一级结构无处可见:double[N][M]
中的各种子数组从基址和大小中是隐含的。
double[3][2]
+----+----+----+----+----+----+
| 00 | 01 | 02 | 10 | 11 | 12 |
+----+----+----+----+----+----+
double**
+------------+------------+
| 0xDEADD00D | 0xDEADBABE |
+------------+------------+
| |
+-----+ |
| |
v |
+----+----+----+ |
| 00 | 01 | 02 | |
+----+----+----+ |
v
+----+----+----+
| 10 | 11 | 12 |
+----+----+----+
所以现在,这已经不碍事了,我们了解了基于double**
的"数组"是如何工作的,我们可以开始尝试解决您的问题了。
要获得double**
,您需要做的是通过用指向单个连续数组中各种地址的指针填充单独的指针数组来自己提供第一级结构。
std::vector<double*> index;
index.reserve(M);
for(int i = 0; i < M; ++i) {
index.push_back(&f[i*N]);
}
double** f2d = index.data();
这为您提供了最小的麻烦和最小的空间开销。它也不执行任何数据副本,因为我们只收集一堆指向现有存储的指针。
您最终会得到如下所示的布局:
index
+------------+------------+
| 0xDEADD00D | 0xDEADBABE |
+------------+------------+
| |
+-----+ +---+
| |
v v
+----+----+----+----+----+----+
f | 00 | 01 | 02 | 10 | 11 | 12 |
+----+----+----+----+----+----+
显然,您无法从数组中获取有效的double**
,因为没有要指向的double*
数组。您需要将平面数组重新解释为二维数组,而不是指针数组。
第一次尝试几乎是正确的;但它将对指针f1d
的引用重新解释为二维数组,而不是它指向的数组。取消引用指针,并重新解释对数组的结果引用,应该可以工作:
double (&f2d)[N][M] = reinterpret_cast<double (&)[N][M]>(*f1d);
^
或者,您可以重新解释对f[0]
的引用,而无需中间指针。
如您所见,使用reinterpret_cast
非常容易出错。您可以考虑将向量包装在一个类中,使用访问器函数来执行二维索引所需的算术。
更新:如果出于某种原因你真的想要一个double**
而不是二维数组,你需要自己构建一个指针数组,
std::vector<double*> pointers;
for (i = 0; i < M; ++i) {
pointers.push_back(&f[i*N]);
}
double** f2d = pointers.data();
- EASTL矢量<向量<int>>连续的
- C - 创建矢量&lt; vector&lt; double&gt;&gt;矩阵具有分配而不是inizializ
- C 字符串比较“祝您好运”&gt;“再见”
- C++20 中的严格别名规则是否允许标准 c++ unicode 字符和下划线类型之间"reinterpret
- 为什么将此对向量&lt; map&lt; int,int&gt;&gt;中的地图进行更新.失败
- C :对矢量进行排序&lt; struct&gt;(结构有2个整数)基于结构的整数之一
- C 操作员&gt;&gt;与突变器过载
- 明确的专业化“ CheckIntmap&lt;&gt;”实例化
- 是否需要使用 - &gt;运算符在C 中调用成员函数时
- 什么是模板&lt;&gt;inline bla bla
- 编辑C Qlist&lt; object*&gt; gt;QML代码和一些QML警告中的模型
- eigen :: llt&lt;eigen :: matrixxd&gt;具有不完整的类型
- 错误,包括&lt; ctype&gt;在原子上使用C 11
- 错误c++visual studio c2227左侧'->;Init';必须指向类/结构/联合/泛型类型
- std::vector<;uint8_t>;当C++11/14启用时,手动复制而不是调用memcpy
- ``这个''不能用this-&gt;指针变量
- 如何加入向量&lt; int&gt;到C 中的单个INT
- 是std :: set&lt; std :: future&gt;不可能存在
- 使用shared_ptr<字符串>转换为一个无序集合<字符串>
- 是numeric_limits&lt; int&gt; :: is_modulo从逻辑上矛盾