【发布时间】:2018-11-28 07:11:18
【问题描述】:
我找到了一些代码,并希望确保我正确理解了这一点。 用例是由值数组表示的打包图像。 在本例中,三个值代表一个像素。
我找到的代码是这样的:
struct Pixel{
int[3] data
int x(){return data[0];}
int y(){return data[1];}
int z(){return data[2];}
};
void main(){
std::vector<int> img(300);
Pixel* access = reinterpret_cast<Pixel*>(img.data()+3*5);
foo(access->x());
}
据我了解POD and standard layout,我认为代码示例是有效的,因为我们只使用了 Pixel 的第一个成员? 然后用
替换像素struct Pixel2{
int red;
int green;
int blue;
};
会导致未定义的行为吗?
编辑: 我与 cuda 合作,发现了另一个例子: 将 unsigned char 指针(一个数组)转换为 uchar3 指针。 uchar3 类型定义等于第二个像素定义。 这是否意味着第二个也有效? 还是这仅适用于 nvcc 编译的代码? 如果第二个 Pixel 定义有效,那为什么?
编辑: 为了进一步强调代码试图做什么,我重命名了上面的一些字段: 我有一组原始数据。在我的情况下,这是一个打包的图像。我想要一种访问像素及其值的好方法。所以我可以这样做:
void bar(int* data,size_t size)
{
Pixel2* img = reinterpret_cast<Pixel*>(data);
std::cout << "Pixel 13 has blue value: " << img[13].blue;
}
我已经看到在 cuda 中使用它的代码并且它有效,但我想知道它是否总是可以的,因为我读到的关于 POD 的内容似乎没有涵盖它。 我只是错过了有关 POD 的一些东西,还是这可能会失败?
编辑: 有没有区别:
foo(access->x());
foo(access->data[0]);
我认为 second 应该是合法的,因为对于 POD 类型,第一个成员变量与对象具有相同的地址?
编辑:我从答案中得到的是:在我提到的所有情况下都是 UB。 那么要走的路就是一个随机访问迭代器,它给我我想要的访问权限。
【问题讨论】:
-
我认为你应该调用一个新的展示位置是正确的,但是,
std::vector解决了完整的问题 -
@JVApen 调用placementy new 究竟要做什么?在向量提供的空间中创建一个新像素?这不是这段代码试图做的。
-
为了解决您的实际问题,您可能应该将
data和size包装到一个类实例中,并使用为您提供所需访问权限的方法,并完全避免reinterpret_cast。一般来说,如果你可以在没有reinterpret_cast的情况下做到这一点,你可能应该这样做。或者,用 C 编写代码(或使用 C++ 的相关 GNU 扩展来允许这样做),并使用带有联合或其他东西的类型双关语...... -
@hyde 考虑用例,该类实例必须是 random_access_iterator。我必须有两个不同的类像素类:一个使用数据,它通过指针知道并由迭代器返回。另一个单独保存数据,可用于保存像素。
标签: c++ c++14 standard-layout