【发布时间】:2021-12-20 22:17:03
【问题描述】:
我是 C++ 新手,最近一直在玩内存分配。我发现当你声明一个带有析构函数的类时,像这样:
class B
{
public:
~B() { }
};
然后像这样创建一个堆数组:
B* arr = new B[8];
分配器分配 12 个字节,但当我删除析构函数时,它只分配 8 个字节。这就是我衡量分配的方式:
size_t allocated = 0;
void* operator new(size_t size)
{
allocated += size;
return malloc(size);
}
void deallocate(B* array, size_t size)
{
delete[] array;
allocated -= size * sizeof(B);
}
当然,我必须手动调用deallocate,而自动调用new 运算符。
我在使用std::string* 时发现了这个问题,我意识到释放器在int* 上工作得很好,但在前者上却不行。
有谁知道为什么会发生这种情况,更重要的是:如何在运行时以编程方式检测这些?
提前致谢。
【问题讨论】:
-
“如何在运行时以编程方式检测这些?” - 你为什么要这样做?
-
@Dai 我只是想看看 C++ 是如何工作的。为什么不应该这样使用
malloc? -
我的评论不是关于特别使用
malloc- 但如果你把它作为一种心理锻炼,那很好;我只是担心你可能会在生产代码中这样做。我删了。 -
"我想知道 malloc 出了什么问题" --
malloc可以在new实现中使用,但它需要保持一致。你不能delete[]分配了malloc的内存——它们是不同的函数,它是正式的未定义行为。见In what cases do I use malloc and/or new? 和Behaviour of malloc with delete in C++ -
这是一个猜测,所以我不想发布答案,但是 - 添加一个非默认析构函数会使该类不易被破坏。释放一个可平凡破坏的对象数组只需要调用
free(),但对于非平凡可破坏的对象,您还必须调用析构函数。额外的 8 个字节将作为编译器的簿记数据,它可能在那里存储元素数量,以便在释放内存之前可以运行正确数量的析构函数。
标签: c++ memory-management heap-memory destructor allocation