【发布时间】:2011-09-13 16:02:11
【问题描述】:
让我先说一下,我知道我将要提出的建议是一种致命的罪过,即使考虑到它,我也可能会在编程地狱中燃烧。
也就是说,我仍然想知道是否有任何原因导致这不起作用。
情况是:我有一个引用计数智能指针类,我到处都在使用它。它目前看起来像这样(注意:不完整/简化的伪代码):
class IRefCountable
{
public:
IRefCountable() : _refCount(0) {}
virtual ~IRefCountable() {}
void Ref() {_refCount++;}
bool Unref() {return (--_refCount==0);}
private:
unsigned int _refCount;
};
class Ref
{
public:
Ref(IRefCountable * ptr, bool isObjectOnHeap) : _ptr(ptr), _isObjectOnHeap(isObjectOnHeap)
{
_ptr->Ref();
}
~Ref()
{
if ((_ptr->Unref())&&(_isObjectOnHeap)) delete _ptr;
}
private:
IRefCountable * _ptr;
bool _isObjectOnHeap;
};
今天我注意到sizeof(Ref)=16。但是,如果我删除布尔成员变量 _isObjectOnHeap,sizeof(Ref) 会减少到 8。这意味着对于我的程序中的每个 Ref,有 7.875 个浪费的 RAM 字节......并且有很多很多 @ 987654327@ 在我的程序中。
嗯,这似乎是在浪费一些 RAM。但我真的需要额外的信息(好吧,让我幽默一下,为了讨论,我假设我真的这样做了)。而且我注意到,由于IRefCountable 是一个非 POD 类,它(可能)总是被分配在一个字对齐的内存地址上。因此,(_ptr) 的最低有效位应始终为零。
这让我想知道......有什么理由我不能将我的一位布尔数据 OR 到指针的最低有效位中,从而在不牺牲任何功能的情况下将 sizeof(Ref) 减少一半?当然,在取消引用指针之前,我必须小心地取消该位,这会降低指针取消引用的效率,但这可能会通过 Refs 现在更小,因此更多的事实来弥补可以立即放入处理器的缓存中,依此类推。
这是合理的做法吗?还是我在为一个受伤的世界做好准备?如果是后者,我究竟会受到怎样的伤害? (请注意,这是需要在所有相当现代的桌面环境中正确运行的代码,但它不需要在嵌入式机器或超级计算机或任何类似的奇异计算机中运行)
【问题讨论】:
-
Boost 中使用了该技巧 - 请参阅 the boost::multi_index 文档的末尾。
-
>> 浪费了 7.875 字节的 RAM。什么?你有模拟字节吗?
-
好吧,7 个字节的填充,加上最后一个字节中的 7 位未使用,因为布尔值只需要一位。有点像普通家庭有 2.5 个孩子 :)
-
是否允许回答我们可以跳过
bool变量的方式? -
在 x86 上,您可能最好使用高位,因为在大多数 ABI 上,该空间是为内核保留的(并且由于在 x86 上,您可以轻松地获得未对齐的指针,尽管正如您所说的那样非 POD 分配器永远不会做一个)。无论您使用什么位,您都应该确保在您的构造函数中检查该位在进入时被清除。
标签: c++ bit-manipulation smart-pointers