目前正在学习 C++,我正在重新访问一个小型内存管理器,我们的教授已经部分将其作为练习编写,并且由于我太长时间忽视了我的 C++ 技能,所以我无法理解内存和新布局的实际工作原理.所以基本上我有多个 Bucket 对象,它们都包含一定数量的 block ,每个 block 都可以有一定数量的内存。 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]);
}
}
所以这里的这段代码让我很困惑。一个桶的大小为 16 字节(如 sizeof(Bucket) 所述,桶的数量为 5。这意味着 m_baseMemory 分配了 80 字节的 ram 并且是一个字符指针(reinterpret_cast 是如何工作的,为什么它被使用两次?)。接下来,通过将内存地址从之前转换为 Bucket 指针来创建一个 bucket 指针 - 究竟是如何以及为什么?当我输出两个地址时,它们彼此非常不同。我理解前两个的方式lines是分配了80字节的内存,其地址保存在m_baseMemory中。然后,因为我们要构造Bucket对象,所以该指针被转换为Bucket指针,这样我们就可以遍历for中的Bucket-addresses循环(基本上一个 i 是 i*sizeof(Bucket) 的偏移量,所以 i*16,对吗?)没有具体说明每个 Bucket 对象所需的偏移量。
那么,由于在 &base_pointer[i] 位置使用了 placement new,它们不应该相同吗?我不明白这两种内存地址(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。老实说,我不明白这是如何计算的,所以不胜感激。
谢谢。
最佳答案
造成混淆的主要原因是,当您应该查看其值时,您却查看了 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]
也是如此。
关于c++ - 使用 placement new 了解 C++ 中的内存访问,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39948194/