带自定义分配器的shared_ptr,其删除器存储位置是否有标准规定?
咱们来逐个解答你的两个问题,结合C++标准和常见实现的情况来说明:
其实这得看具体实现,但大多数主流实现(比如GCC的libstdc++、Clang的libc++)会把删除器和shared_ptr的控制块(包含引用计数、弱引用计数等核心数据)放在一起,而控制块正是通过你指定的自定义分配器来分配内存的。
不过要注意:标准并没有强制要求删除器必须被存储在分配器分配的内存里。如果你的删除器是一个非常小的对象(比如空函数对象、或者大小可以被优化的类型),有些实现可能会做“小对象优化”,甚至直接把删除器的信息嵌入到shared_ptr本身的结构里,但这种情况比较少见。绝大多数场景下,删除器会跟着控制块一起,存放在自定义分配器分配的内存区域中。
问题2:这属于未指定行为,还是我遗漏了相关内容?
你没看错,C++标准确实没有对删除器的具体存储位置做明确规定——既没要求必须用自定义分配器为删除器单独分配内存,也没禁止这么做。这种情况属于未指定行为:标准只规定了shared_ptr的对外行为(比如正确调用删除器、正确管理引用计数),但把控制块的内部布局、删除器的存储方式这类细节交给了实现厂商来决定。
换句话说,你不能依赖删除器的存储位置来写代码,因为不同编译器、不同版本的标准库可能会有不同的实现方式,但只要符合标准的行为要求,都是合法的。
内容的提问来源于stack exchange,提问作者Lightness Races in Orbit




