如何实现自带大小记录的智能数组指针?
带大小追踪的智能缓冲区实现方案
首先直接回答你的问题:不建议直接继承std::unique_ptr<byte[]>。原因很简单——std::unique_ptr没有虚析构函数,如果后续把这个子类对象当作基类std::unique_ptr来使用(比如赋值给基类指针),析构时会跳过子类的成员清理,虽然你的场景里可能只是加个size字段不会有内存泄漏,但这属于违反标准库类型的设计意图,是不安全的实践。
更合适的做法是包装std::unique_ptr,同时封装size字段并提供和原生unique_ptr一致的接口,这样既满足带大小追踪的需求,又能保持使用的简洁性,代码量其实并不大。以下是一个符合你需求的实现:
#include <cstdlib> #include <memory> #include <cstddef> using byte = unsigned char; class SmartBuffer { public: // 构造:分配指定大小的缓冲区 explicit SmartBuffer(size_t size) : m_size(size), m_buffer(static_cast<byte*>(std::malloc(size)), std::free) {} // 禁止拷贝(保持独占所有权,和unique_ptr一致) SmartBuffer(const SmartBuffer&) = delete; SmartBuffer& operator=(const SmartBuffer&) = delete; // 允许移动 SmartBuffer(SmartBuffer&&) = default; SmartBuffer& operator=(SmartBuffer&&) = default; // 访问元素,和数组/unique_ptr行为一致 byte& operator[](size_t idx) { return m_buffer[idx]; } const byte& operator[](size_t idx) const { return m_buffer[idx]; } // 获取原始指针 byte* get() { return m_buffer.get(); } const byte* get() const { return m_buffer.get(); } // 释放所有权,交给C库(C库后续调用free) byte* release() { m_size = 0; return m_buffer.release(); } // 获取缓冲区大小 size_t size() const { return m_size; } // 检查是否为空 bool empty() const { return m_size == 0; } private: size_t m_size = 0; std::unique_ptr<byte[], decltype(&std::free)> m_buffer{nullptr, std::free}; };
这个实现的优势:
- 完全满足你的需求:用malloc/free分配内存,追踪缓冲区大小,支持release()交给C库,无拷贝开销
- 使用体验和原生unique_ptr几乎一致:可以用
[]访问元素,get()取指针,release()释放所有权 - 保持了unique_ptr的独占语义,避免拷贝导致的所有权混乱
- 比继承unique_ptr更安全,符合C++标准库的设计规范
至于你疑惑的「为什么原生unique_ptr不带size字段」——因为std::unique_ptr的核心职责是管理指针的独占所有权,而缓冲区大小属于数据的元信息,不属于指针本身的职责。标准库倾向于将单一职责的组件拆分,比如std::vector同时管理内存、大小和容量,但vector的内存分配依赖于allocator,无法直接和C库的malloc/free无缝配合(除非自定义allocator),这也是你需要自定义智能缓冲区的原因。
内容的提问来源于stack exchange,提问作者Dylan Bradshaw
相关产品推荐
相关产品推荐

