如何在创建后正确填充对象而不修改类声明

How to correctly pad an object after creation without modifying the class declaration?

本文关键字:对象 修改 声明 填充 创建      更新时间:2023-10-16

我想知道是否有办法在实例化后填充对象。假设一个从类 Foo 实例化的对象,实现如下:

class Foo
{
    size_t addr;
    unsigned allocationNum;
public:
    Foo()
    {
        addr = (size_t)this;
        allocationNum = 0;
    }
    ~Foo()
    {
        addr = 0;
        allocationNum = 0;
    }
    void SetAllocNum(unsigned nAllocationNum)
    {
         allocationNum = nAllocationNum;
    }
    unsigned GetAllocNum() const
    {
        return allocationNum;
    }
    size_t GetAddress() const
    {
        return addr;
    }
};

然后通过 Foo* object = new Foo(); 创建对象的实例。有没有办法说添加到对象,以便(size_t)objectsizeof(*object)将其显示为更大的对象?另外,当说将标准数据类型(如char*)强制转换为此对象时,有没有办法填充该强制转换以使char*适合它所强制转换为的对象的大小?我问这些问题有点出于好奇,因为我觉得这可能会解决我的程序遇到的问题。以下是具体背景:

T* AddObject()
{
   T* object = new T(); // Here is the new object T=Foo in this case.
   *(T*)(buffer+position) = *object; // Being stored in a char* buffer at current empty position
   T* returnValue = &(*(reinterpret_cast<T*>(buffer+position))); 
   //  ^ Here I try casting the char* buffer@position with the object contents stored inside the buffer.
   return returnValue;
}

这样做的问题是它在某种程度上将其强制转换为 T 对象,但大小仍然是缓冲区的大小。在 main 中执行sizeof(*object)将显示我认为对象的大小应该是多少,但如果我将 Foo* object = new Foo()(size_t) objectFoo* differentObj = AddObject()(size_t)differentObj进行比较,则(size_t)differentObj将与(size_t)buffer相同,但与(size_t)object不同。也许是因为我不明白size_t所代表的是什么与sizeof内存中的对象是否具有我不确定的位数不同。至少据我所知sizeof表示变量或类型占用的内存量(以字节为单位)。

您是否意识到(size_t)object没有为您提供任何大小,而是将对象转换为类型size_t(通常定义为无符号整数)的(c样式)?例如,请参阅此size_t文档。 sizeof(请参阅此处的文档)返回一个类型为 size_t 的值,可能这就是您对它的困惑的来源?

您可能希望一直使用sizeof。不过,要小心你传递给sizeof的东西。 例如,sizeof(Foo*)将为您提供指向Foo的指针的大小,而不是Foo对象的大小。对于后者,您必须使用 sizeof(Foo) .

(sizeof)x在编译时计算,并通过类型定义进行计算;如果x是用户定义的类型,则由结构或类接口计算。所以除了改变接口之外,没有办法改变sizeof的结果。

如果你想在特定地址构造一个对象,你应该使用放置 new:

T* AddObject()
{
    return new (buffer+position) T();
}

请注意,如果使用此版本的 new,则不能使用默认删除。

sizeof是一个编译时运算符,它将从类型中生成其值。它不能重载,并且返回值的类型为 size_tsize_t 是在标准库中定义的无符号整数类型。

在编写(size_t)differentObj时,您从T*投射到size_t。这是有效的,但通常不是人们想要做的事情。如果要以精确字节为单位计算两个指针之间的偏移量,请说reinterpret_cast<char*>(pointer1) - reinterpret_cast<char*>(pointer2).

当两个指针具有相同的值时(例如 (size_t)differentObj == (size_t)buffer )表示它们指向同一对象。(这意味着在您的示例中,position必须设置为 0

无论如何,您应该仅在确实需要时才使用这些技术,因为指针摆弄会使代码变得非常复杂。