可以将无关数据存储在指针的最低有效位中吗?

Jer*_*ner 12 c++ bit-manipulation smart-pointers

让我先说一下,我所知道的是我要提出的是一个致命的罪,并且即使考虑它,我也可能会在编程地狱中燃烧.

也就是说,我仍然有兴趣知道为什么这不起作用.

情况是:我有一个我在任何地方使用的引用计数智能指针类.它目前看起来像这样(注意:不完整/简化的伪代码):

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;
};
Run Code Online (Sandbox Code Playgroud)

今天我注意到sizeof(Ref)= 16.但是,如果我删除布尔成员变量_isObjectOnHeap,则sizeof(Ref)减少到8.这意味着对于我的程序中的每个Ref,有7.875个浪费的RAM字节......并且我的程序中有很多很多Refs .

好吧,这似乎浪费了一些内存.但我真的需要那些额外的信息(好吧,幽默我,并为了我真正做的讨论而假设).我注意到,由于IRefCountable是一个非POD类,它(可能)总是被分配在一个字对齐的内存地址上.因此,(_ptr)的最低有效位应始终为零.

这让我想知道...有什么理由说我不能将我的一点布尔数据或指针的最低有效位,并因此将sizeof(Ref)减少一半而不牺牲任何功能?当然,在取消引用指针之前,我必须小心取出那个位,这会使指针解引用效率降低,但这可能是因为Refs现在更小,因此更多可以立即适应处理器的缓存,依此类推.

这是合理的事吗?还是我为自己创造了一个受伤的世界?如果是后者,那么伤害到底是怎么回事?(请注意,这是需要在所有合理的现代桌面环境中正确运行的代码,但它不需要在嵌入式计算机或超级计算机或任何异国情况下运行)

Ano*_*mie 1

任何原因?除非最近标准发生了变化,否则指针的值表示是实现定义的。当然,某些地方的某些实现可能会采用相同的技巧,为自己的目的定义这些原本未使用的低位。更有可能的是,某些实现可能使用字指针而不是字节指针,因此两个相邻的字不是位于“地址”0x8640 和 0x8642,而是位于“地址”0x4320 和 0x4321。

解决该问题的一种棘手方法是使 Ref 成为(事实上的)抽象类,并且所有实例实际上都是 RefOnHeap 和 RefNotOnHeap 的实例。如果周围有那么多 Ref,则用于存储三个类(而不是一个类)的代码和元数据的额外空间将由每个 Ref 大小减半所节省的空间来弥补。(效果不太好,如果没有虚拟方法,编译器可以省略 vtable 指针,并且引入虚拟方法会将 4 或 8 字节添加回类中)。