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

C++20前std::unique_ptr如何对lambda闭包应用EBO?

关于std::unique_ptr结合lambda删除器的空基类优化(EBO)问题

测试代码

#include <memory>
#include <cstdio>

int main(){
    auto x1 = [](int *p){ delete(p); };
    auto ptr = std::unique_ptr<int, decltype(x1)>(new int{1}, x1);
    printf("%zu\n", sizeof(ptr)); // 输出8,看似出乎意料
}

问题核心

测试代码中使用lambda作为删除器的std::unique_ptr实例大小为8字节,结合已知信息:

  • 空基类优化(EBO)可通过继承空基类避免额外占用对象内存
  • 微软STL中std::unique_ptr通过_Compressed_pair存储删除器与指针,该类特化版本会在第一个类型为空且非final时继承它

存在疑问:C++20前lambda闭包类型无默认构造函数,继承该类型的_Compressed_pair如何实例化?std::unique_ptr又如何对闭包应用EBO?


解答

1. 核心逻辑:无需默认构造,靠拷贝构造初始化

lambda闭包类型没有默认构造函数,但**_Compressed_pair不需要默认构造它**——因为std::unique_ptr的构造是从外部传入已构造完成的lambda实例的:

  • 当你调用std::unique_ptr<int, decltype(x1)>(new int{1}, x1)时,已经把现成的lambda对象x1传给了构造函数
  • _Compressed_pair会通过拷贝构造来初始化继承的lambda基类部分,而不是依赖默认构造。这里的lambda是空捕获,闭包类型支持拷贝构造,完全满足需求

2. EBO的具体应用

因为当前lambda是空捕获的闭包类型,属于空类型(没有非静态数据成员),所以_Compressed_pair会触发特化逻辑,直接继承这个lambda闭包类型:

  • 空基类优化生效后,继承的空类型不会占用额外内存空间
  • _Compressed_pair的总大小就等于存储指针的大小(64位系统下为8字节),因此整个std::unique_ptr实例的大小就是8字节

3. 关于C++20前lambda的限制

C++20前lambda确实没有默认构造函数,但这只会限制默认构造_Compressed_pair或std::unique_ptr的场景,不会影响用已存在的lambda实例进行拷贝构造的情况。而std::unique_ptr带删除器参数的构造函数,正好是用传入的删除器实例初始化内部的_Compressed_pair,完美绕开了默认构造的需求


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 07:50:16