使用placement new了解C ++中的内存访问

时间:2016-10-09 20:25:19

标签: c++ pointers memory-management

目前正在学习C ++,我正在重新审视一个小型内存管理器,我们的教授部分写作练习,因为我已经忽略了我的C ++技能太久了,我很难理解内存和放置新的实际工作。所以基本上我有多个Bucket对象都拥有一定数量的块,每个块都可以有一定的内存。 BucketAdmin类包含所有Bucket对象。

BucketAdmin::BucketAdmin(void)
{
m_baseMemory = reinterpret_cast<unsigned char *>(malloc(sizeof(Bucket) * NUM_OF_BUCKETS) );

Bucket* base_pointer = reinterpret_cast<Bucket*>(m_baseMemory);
std::cout << &base_pointer<< "     "  <<  &base_pointer + sizeof(Bucket) *     NUM_OF_BUCKETS  << "     " << sizeof(Bucket) * NUM_OF_BUCKETS << std::endl;

for (unsigned short i = 0; i < NUM_OF_BUCKETS; i++)
{
    m_buckets[i] = new (&base_pointer[i])Bucket(m_bucketSizes[i], BUCKET_CAPACITY/m_bucketSizes[i]);
}
}

所以这里的代码令我困惑。 Bucket的大小为16字节(由sizeof(Bucket)表示,桶的数量为5.这意味着m_baseMemory分配80个字节的ram并且是一个char指针(reinterpret_cast如何正确工作以及为什么它使用了两次)接下来,通过将之前的内存地址转换为Bucket指针来创建一个存储桶指针 - 究竟是怎样以及为什么?当我输出两个地址时,它们彼此非常不同。我理解前两个的方式lines是分配了80个字节的内存,其地址保存在m_baseMemory中。然后,因为我们想要构造Bucket对象,所以指针被转换为Bucket指针,这样我们就可以迭代遍历Bucket-adresses中的for-循环(基本上一个i是i * sizeof(Bucket)的偏移量,所以i * 16,正确吗?)没有特别说明每个Bucket对象所需的偏移量。

因此,当位置&amp; base_pointer [i]使用新位置时,它们是否应该相同?我不明白这两种内存地址(m_baseMemory,base_pointer)是如何彼此如此不同的。当我将base_pointer地址与base_pointer地址加上分配的内存进行比较时,我应该得到一个80更大(十进制)的地址,但是当我比较这些数字时,它会有数百的差异?一个例子: base_pointer地址是:010FFA6C base_pointer地址+ sizeof(Bucket)* NUM_OF_BUCKETS为:010FFBAC

即使sizeof(Bucket)* NUM_OF_BUCKETS = 80将被解释为十六进制,它也会添加128(8 * 16),而不是320,就像这里的情况一样。老实说,我不明白这是如何计算的,所以我们将不胜感激。

谢谢。

1 个答案:

答案 0 :(得分:1)

混淆的主要原因是,当您应该查看其值时,您正在查看base_pointer的地址。

您似乎错过的另一件事是将k添加到指针会将k + sizeof(what the pointer points to)添加到地址。

&base_pointer是变量的地址,而不是分配的内存,因此&base_pointer + sizeof(Bucket) * NUM_OF_BUCKETS是距离它的地址80 * sizeof(Bucket*)字节。
80 * sizeof(Bucket*)在32位目标上是320。

您感兴趣的地址是base_pointer; m_baseMemory + k * sizeof(Bucket)base_pointer + k表示相同的地址,&base_pointer[k]也是如此。