在不复制数据的情况下,将double数组转换为只有double成员的structs数组
Convert an array of doubles to an array of structs with only double members without copying data
我正在使用第三方C++库在Julia中做一些繁重的工作。在Julia方面,数据存储在类型为Array{Float64, 2}
的对象中(这大致类似于替身的2D阵列(。我可以使用指向double
的指针将其传递给C++。然而,在C++方面,数据存储在一个名为vector3
:的结构中
typedef struct _vector3
{
double x, y, z;
} vector3;
我的快速而肮脏的方法是一个五步过程:
- 在C++端动态分配结构数组
- 将输入数据从
double*
复制到vector3*
- 进行重型吊装
- 将输出数据从
vector3*
复制到double*
- 删除动态分配的阵列
复制大量数据的效率非常低。是否有一些神秘的技巧可以用来避免将数据从double
复制到struct
再复制回来?我想以某种方式将double
的1D数组(大小为3的倍数(解释为具有3个double
成员的结构的1D阵列。
很遗憾,你不能。这是因为C++具有混叠规则。简而言之,如果您有一个对象T
,您就不能从不兼容类型U
的指针合法访问它。从这个意义上说,您不能通过struct _vector3
类型的指针访问double
或double*
类型的对象,反之亦然。
如果你深入挖掘,你会发现reinterpret_cast
,也许会想"哦,这正是我需要的",但事实并非如此。无论你用什么手段(reinterpret_cast
或其他方式(绕过语言限制(也称为,只是让它编译(,事实仍然是,你只能通过double
类型的指针合法访问double
类型的对象。
键入双关语常用的一个技巧是使用union
。在C
中是合法的,但在C++中是非法的,但一些编译器允许这样做。然而,在你的情况下,我认为没有办法使用并集。
理想的情况是直接对double*
数据进行重载。如果这在您的工作流程中可行。
严格来说,你不能。我以前问过一个类似的问题(用C++的方式别名结构和数组(,答案解释了为什么直接别名会调用Undefined Behavior,并给出了一些可能的解决方案。
话虽如此,你已经陷入了困境,因为原始数据来自不同的语言。这意味着该数据的处理不在C++标准的范围内,仅由您正在使用的实现(gcc/version或clang/version或…(定义
对于您的实现,将外部数组别名为C++结构或将外部结构别名为C++数组可能是合法的。您仔细阅读了混合语言编程的文档,以便进行精确的实现。
其他答案提到了真正的问题(转换可能无法正常工作(。我将添加一个小的运行时检查,以验证别名是否有效,并提供一个占位符,用于调用/使用大量复制的代码。
int aliasing_supported_internal() {
double testvec[6];
_vector3* testptr = (_vector3*)(void*)testvec;
// check that the pointer wasn't changed
if (testvec != (void*)testptr) return 0;
// check for structure padding
if (testvec+3 != (void*)(testptr+1)) return 0;
// TODO other checks?
return 1;
}
int aliasing_supported() {
static int cached_result = aliasing_supported_internal();
return cached_result;
}
此代码将一个小的doubles数组转换为一个结构别名数组(不是复制(,然后检查它是否有效。如果转换有效(函数返回1(,您可能可以自己使用相同类型的别名(通过空指针进行转换(。
请注意,代码仍可能以意外方式被破坏。严格的混叠规则规定,即使是上述检查也是未定义的行为。这可能奏效,也可能失败。只有允许正常工作的转换才能作废*并返回到原始指针类型。此外,在多个继承层次结构或虚拟基类中,上述检查可能是完全错误的(从某种意义上说,两者都不安全地转换为void*,因为实际指针值可能会发生偏移,也就是说,可能会由于对齐以外的约束而发生变化,并且偏移了相当多的字节(
- 在c++中为double类型的数组创建一个unique_ptr
- 在不复制数据的情况下,将double数组转换为只有double成员的structs数组
- 是否可以输入到const double数组
- 错误:数组大小表达式必须具有整型或无作用域枚举类型,而不是'double'
- 错误:无法将参数“1”的“double*”转换为“double”,错误:数组下标的类型“double[double]”无
- C++ 错误错误:数组下标的类型"双精度 [10][10][double]"无效
- 如何使用向量中包含的double[4][4]数组
- 错误:数组下标'double*[double]'的类型无效
- PTXAS 在结构数组上使用 thrust::sort 时"double is not supported"警告
- 使用double-for循环索引一维数组
- 当我从int切换到double时,数组中出现了奇怪的反馈
- 使用float 2d数组的C++内存泄漏,如果我使用double,则会消失
- 在 c++ 中显示大小未知的 'double' 数字数组
- c++mex错误:数组下标的类型“double[mwSize]”无效
- 如何在 C# 中从 com 对象返回数组(double[])
- 将表示二维数组的 std::vector<std::vector <double> >转换为 cv::Mat
- 实现动态数组数据结构时出现"double free or corruption"错误
- 将二维数组 double[][] 传递给 c# 窗口应用程序
- 声明 double* 数组时出现损坏的堆错误
- 将const double[][]数组作为参数传递给double**接口