我有一个旨在存储用户定义数据(即从插件)的结构.它具有这样的char[]具有给定最大尺寸的存储该数据.
struct A
{
// other members omitted
// data meant to be type punned, only contains PODs
char data[256];
};
Run Code Online (Sandbox Code Playgroud)
然后是一个示例用户结构,它具有一个静态函数来自己投射A.
struct B
{
int i;
double d;
static B& FromA_ref(A& a)
{
// static_assert that sizeof(B) < sizeof(A::data)
return * reinterpret_cast<B*>(a.data);
}
};
Run Code Online (Sandbox Code Playgroud)
我编译g++ -O3 -std=c++0x -Wall -o test test.cpp(GCC 4.6.1).
这会触发dereferencing type-punned pointer will break strict-aliasing rules警告.我认为这样可以,因为我使用了一个char[]存储器,我认为它将遵循相同的规则char*.我觉得很奇怪,事实并非如此.不是吗?好吧,......我现在无法改变它,所以让我们继续吧.
现在让我们考虑以下方法:
struct B
{
....
static B* FromA_ptr(A& a)
{
// static_assert that sizeof(B) < sizeof(A::data)
return reinterpret_cast<B*>(a.data);
}
}
Run Code Online (Sandbox Code Playgroud)
由于我在这里没有取消引用任何内容,GCC不会输出任何警告.当我B稍后使用指针时也不会这样做.
A a;
auto b = B::FromA_ptr(a);
b->i = 2; // no warnings.
Run Code Online (Sandbox Code Playgroud)
但是这样做是否安全?我觉得我一直在解决问题而不是解决问题.对我->来说仍然以某种方式取消引用变量.
或者,有没有更好的方法来实现这种效果?IE从另一个结构中的存储中获取可修改的引用(或指针)?(Union将无法工作,因为存储的类型集在A定义时是未知的,有些可能通过插件添加,memcpy会迫使我来回复制数据,尽管它似乎是目前唯一安全的方式)