You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

自定义operator delete[]中如何获取总分配内存大小?

如何在类专属operator delete[]中合法获取释放的内存大小?

你遇到的核心问题是:类专属的operator delete[]默认重载只有void*参数,无法直接获取要释放的内存总大小,但C标准(C11及以后)提供了带std::size_t参数的operator delete[]重载形式,编译器会自动传递对应的内存大小,完全不需要额外分配空间存储计数,合法且高效。

解决方案:重载带std::size_t参数的operator delete[]

直接修改X<Id>的operator delete[]实现,添加std::size_t参数,这个参数会由编译器自动传入当前要释放的内存总字节数,和你在operator new[]中拿到的count完全对应。

修改后的完整代码:

#include <cstdio>
#include <string>
#include <vector>

template <int Id>
struct X {
    static inline int held = 0;
    static void* operator new(std::size_t count)
    {
        held += count;
        return ::operator new(count);
    }
 
    static void* operator new[](std::size_t count)
    {
        held += count;
        return ::operator new[](count);
    }

    static void operator delete(void* ptr)
    {
        held -= sizeof(X<Id>);
        ::operator delete(ptr);
    }

    // 重载带std::size_t参数的版本,编译器自动传递内存大小
    static void operator delete[] (void* ptr, std::size_t count)
    {
        held -= count;
        ::operator delete[] (ptr);
    }

    std::string s1;
    std::vector<int> v1;
};

int main() {
    auto * dx2 = new X<1>[100];
    printf("x1d2 %d\n", X<1>::held);
    delete [] dx2;
    printf("x1d2 released %d\n", X<1>::held); // 现在输出为0,符合预期
}

关键说明

  1. 合法性:这个带std::size_t参数的operator delete[]是C标准明确规定的重载形式,所有符合C11及以后标准的编译器(GCC、Clang、MSVC等)都支持,完全属于标准行为,不存在依赖编译器私有实现的问题。
  2. 准确性:传入的count值和operator new[]中接收的总内存字节数完全一致,所以held的加减能准确反映当前堆上的内存持有量,不需要额外处理对象数量或额外开销。
  3. 兼容性:如果需要兼容旧编译器(C03及以前),这种方法不可用,但目前主流开发环境都已支持C11及以上标准,这个限制基本可以忽略。

内容的提问来源于stack exchange,提问作者calvin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 03:27:19