严格的指针别名:针对特定问题的任何解决方案?
我遇到了由于违反严格的指针别名规则而引起的问题。我有一个来自模板的类型 T
和一些相同大小的整数类型 Int
(与 sizeof
一样)。我的代码基本上执行以下操作:
T x = some_other_t;
if (*reinterpret_cast <Int*> (&x) == 0)
...
因为 T
是可以具有构造函数的任意(大小限制除外)类型,所以我无法将 T
和 结合起来>int
。 (这仅在 C++0x 中允许,甚至 GCC 还不支持)。
有什么方法可以重写上面的伪代码以保留功能并避免违反严格的别名规则?请注意,这是一个模板,我无法控制 T
或 some_other_t
的值;赋值和随后的比较确实发生在模板化代码内。
(郑重声明,如果 T
包含任何位字段,则上述代码在 GCC 4.5 上开始损坏。)
I have a problem caused by breaking strict pointer aliasing rule. I have a type T
that comes from a template and some integral type Int
of the same size (as with sizeof
). My code essentially does the following:
T x = some_other_t;
if (*reinterpret_cast <Int*> (&x) == 0)
...
Because T
is some arbitary (other than the size restriction) type that could have a constructor, I cannot make a union of T
and Int
. (This is allowed only in C++0x only and isn't even supported by GCC yet).
Is there any way I could rewrite the above pseudocode to preserve functionality and avoid breaking strict aliasing rule? Note that this is a template, I cannot control T
or value of some_other_t
; the assignment and subsequent comparison do happen inside the templated code.
(For the record, the above code started breaking on GCC 4.5 if T
contains any bit fields.)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
在我的系统上,GCC 优化了
is_T_0()
和memcpy()
,从而在myfunc()
中只生成了一些汇编指令。On my system, GCC optimizes away both
is_T_0()
andmemcpy()
, resulting in just a few assembly instructions inmyfunc()
.您听说过
boost::Optional
吗?我必须承认我不清楚这里的真正问题......但是 boost::Optional 允许按值存储,但知道实际内存是否已初始化。我还允许就地构建和销毁,所以我想这可能是一个不错的选择。
编辑:
我想我终于抓住了这个问题:你希望能够在内存中的不同点分配很多对象,并且你想知道此时的内存是否已分配是否真的持有一个物体。
不幸的是,您的解决方案有一个巨大的问题:它是不正确的。如果
T
可以以某种方式由null
位模式表示,那么您会认为它是统一的内存。您将不得不自己添加至少一点信息。实际上并不算多,毕竟只增长了 3%(33 位对应 4 个字节)。
例如,您可以使用一些模仿
boost::Optional
但以数组方式(以避免填充损失)。那么就这么简单:
注意:为了简单起见,我没有考虑对齐问题。如果您不了解该主题,请在摆弄记忆之前先阅读它:)
Have you heard about
boost::optional
?I must admit I am unclear as to the real problem here... but boost::optional allow to store by value and yet know whether or not the actual memory has been initialized. I also allows in place construction and destruction, so could be a good fit I guess.
EDIT:
I think I finally grasped the problem: you want to be able to allocate a lot of objects, at various points in memory, and you'd like to know whether or not the memory at this point really holds an object or not.
Unfortunately your solution has a huge issue: it's incorrect. If ever
T
can somehow be represented by anull
bit pattern, then you'll think it's unitialized memory.You will have to resort yourself to add at least one bit of information. It's not much really, after all that's only 3% of growth (33 bits for 4 bytes).
You could for example use some mimick
boost::optional
but in an array fashion (to avoid the padding loss).Then it's as simple as that:
note: For simplicity's sake I have not considered the issue of alignment. If you don't know about the subject, read about it before fiddling with memory :)
使用 33 位计算机。 ;-P
Use a 33-bit computer. ;-P
为什么不简单地:(
您可能想尝试将
static
限定符添加到zero
以查看它是否会在性能方面产生差异)Why not simply:
(you may want to try to add also the
static
qualifier tozero
to see if it makes a difference performance-wise)怎么样:
它可能没有那么有效,但它应该消除警告。
附录 #1:
由于
T
被限制为与Int
相同的大小,因此将自己设置为T
类型的虚拟按位零值并直接比较反对它(而不是与Int(0)
进行转换和比较)。如果你的程序是单线程的,你可以有这样的东西:
如果它是多线程的,你会想要避免使用静态成员
zero_
,并让每个容器实例拥有它自己的< code>zero_ 成员:附录#2:
让我用另一种更简单的方式来表达上述附录:
How about this:
It might not be as efficient, but it should get rid of the warning.
ADDENDUM #1:
Since
T
is constrained to be the same size asInt
, make yourself a dummy bitwise zero value of typeT
and compare directly against it (instead of casting and comparing agaistInt(0)
).If your program is single-threaded, you could have something like this:
If it is multi-threaded, you'll want to avoid using a static member
zero_
, and have each container instance hold it's ownzero_
member:ADDENDUM #2:
Let me put the above addendum in another, simpler way: