英文:
Passing Vector3D struct into pointer-based API
问题
I'm working with VTK and it's API requires all calls to be invoked either with double*
or with double[3]
. So the methods accept a pointer to some point in 3D space.
I've created the Vector3D
struct, that is the simple aggregate:
struct Vector3D
{
double x;
double y;
double z;
};
And now I want to use it for VTK API, because VTK doesnt have Point3D
/ Vector3D
struct itself and using raw pointers is weird.
So, I've used the following method:
double* ptr() noexcept
{
// I'm not totally sure, maybe it'd be better to use `reinterpret_cast<...>(&x)` here
return reinterpret_cast<double*>(this);
}
And that worked, but now I realized that I need the const
overload too.
const double* ptr() const noexcept
{
return reinterpret_cast<const double*>(this);
}
But I didnt see any cases, where the reinterpret_cast<const T*>
was used.
And it got me thinking: "Am I doint it right?"
英文:
I'm working with VTK and it's API requires all calls to be invoked either with double*
or with double[3]
. So the methods accept a pointer to some point in 3D space.
I've created the Vector3D
struct, that is the simple aggregate:
struct Vector3D
{
double x;
double y;
double z;
};
And now I want to use it for VTK API, because VTK doesnt have Point3D
/ Vector3D
struct itself and using raw pointers is weird.
So, I've used the following method:
double* ptr() noexcept
{
// I'm not totally sure, maybe it'd be better to use `reinterpret_cast<...>(&x)` here
return reinterpret_cast<double*>(this);
}
And that worked, but now I realized that I need the const
overload too.
const double* ptr() const noexcept
{
return reinterpret_cast<const double*>(this);
}
But I didnt see any cases, where the reinterpret_cast<const T*>
was used.
And it got me thinking: "Am I doint it right?"
答案1
得分: 0
是的,这没问题。如果你想要更加谨慎,你可以添加static_assert(sizeof(Vector3D) == sizeof(double) * 3);
,但它可能永远不会触发。
从正式的角度来看,如果你尝试通过这个指针访问除了 x
以外的任何成员,行为是未定义的,因为+
/-
/[i]
(带有非零偏移)只能用于通过指向不同元素的指针来访问数组的元素,而你没有一个数组。
然而,在实际应用中,使用指针的代码可能隐藏在不同的翻译单元中(可能是一个库),阻止编译器注意到未定义的行为并基于此进行优化。即使在同一翻译单元中使用,编译器也不太可能破坏这样的代码。
英文:
Yes, this is fine. You can add static_assert(sizeof(Vector3D) == sizeof(double) * 3);
if you want to be extra cautious, but it will probably never fire.
Formally, the behavior is undefined if you try to access any member other than x
through this pointer, since +
/-
/[i]
(with nonzero offset) can only be used to reach an element of an array through a pointer to a different element, and you don't have an array.
However, in practice, the code using the pointer is likely hidden in a different translation unit (possibly a library), preventing the compiler from noticing the UB and being able to optimize based on that. Even if used in the same translation unit, it's unlikely that a compiler would break such code.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论