我们刚刚将编译器升级到 gcc 4.6,现在我们收到了一些警告。目前我们的代码库还没有处于使用 c++0x 编译的状态,无论如何,我们不想在 prod 中运行它(至少现在还没有) - 所以我需要修复来删除这个警告。
警告通常是由于以下原因而发生的:
struct SomeDataPage
{
// members
char vData[SOME_SIZE];
};
稍后,这是通过以下方式使用的
SomeDataPage page;
new(page.vData) SomeType(); // non-trivial constructor
例如,要读取、更新和返回,曾经发生过以下转换
reinterpret_cast<SomeType*>(page.vData)->some_member();
4.4 没问题;在 4.6 中,上述生成:
警告:类型双关指针会破坏严格的别名规则
现在消除此错误的一种干净方法是使用 a union
,但是就像我说的那样,我们不能使用 c++0x (因此不能使用不受限制的联合),所以我使用了下面可怕的 hack - 现在警告已经消失,但是我可能会调用鼻守护程序吗?
static_cast<SomeType*>(reinterpret_cast<void*>(page.vData))->some_member();
这似乎可以正常工作(请参见此处的简单示例:http ://www.ideone.com/9p3MS )并且不会产生任何警告,在 c++0x 之前使用它是否可以(不是在风格上)?
注意:我不想-fno-strict-aliasing
一般使用...
编辑:看来我弄错了,4.4 版也有同样的警告,我想我们最近才发现这个变化(它总是不太可能是编译器问题),但问题仍然存在。
编辑:进一步调查产生了一些有趣的信息,似乎在一行中进行强制转换和调用成员函数是导致警告的原因,如果代码分为如下两行
SomeType* ptr = reinterpret_cast<SomeType*>(page.vData);
ptr->some_method();
这实际上不会产生警告。结果,我在 ideone 上的简单示例存在缺陷,更重要的是,我上面的 hack 没有修复警告,修复它的唯一方法是将函数调用与强制转换分开 - 然后强制转换可以保留为reinterpret_cast
.