如何自动判断C++内存是通过scalar new还是array new分配的?
解决智能指针自动区分标量/数组类型的方案
你可以通过以下几种方式实现自动判断,无需手动传入布尔值:
1. 工厂函数区分场景
提供专门的工厂函数来分别创建标量和数组类型的智能指针,内部自动设置标记位,代码更直观且不易出错:
template<typename T> class Pointer { public: // 私有构造函数,仅让工厂函数调用 Pointer(T* ptr, bool is_array) : m_ptr(ptr), m_is_array(is_array), m_ref_count(new size_t(1)) {} ~Pointer() { if (--*m_ref_count == 0) { m_is_array ? delete[] m_ptr : delete m_ptr; delete m_ref_count; } } // 其他成员函数... private: T* m_ptr; bool m_is_array; size_t* m_ref_count; }; // 创建标量智能指针 template<typename T> Pointer<T> make_pointer(T* ptr) { return Pointer<T>(ptr, false); } // 创建数组智能指针 template<typename T> Pointer<T> make_pointer_array(T* ptr) { return Pointer<T>(ptr, true); }
使用时直接调用对应函数:
auto scalar_ptr = make_pointer(new int(42)); auto array_ptr = make_pointer_array(new int[5]);
2. 封装内存分配逻辑(推荐)
模仿标准库std::make_unique,让工厂函数直接完成内存分配,彻底避免用户手动调用new/new[],从根源上保证分配与释放方式匹配:
// 标量版本:直接构造对象 template<typename T, typename... Args> Pointer<T> make_pointer(Args&&... args) { return Pointer<T>(new T(std::forward<Args>(args)...), false); } // 数组版本:指定大小分配 template<typename T> Pointer<T> make_pointer_array(std::size_t size) { return Pointer<T>(new T[size], true); }
使用示例:
auto scalar_ptr = make_pointer<int>(42); auto array_ptr = make_pointer_array<int>(5);
3. 标签分派提升可读性
用空标签结构体替代布尔值,让构造逻辑更清晰:
// 定义标签 struct scalar_tag {}; struct array_tag {}; template<typename T> class Pointer { public: Pointer(T* ptr, scalar_tag) : m_ptr(ptr), m_is_array(false), m_ref_count(new size_t(1)) {} Pointer(T* ptr, array_tag) : m_ptr(ptr), m_is_array(true), m_ref_count(new size_t(1)) {} // 析构函数及其他成员... }; // 辅助函数 template<typename T> Pointer<T> make_scalar(T* ptr) { return Pointer<T>(ptr, scalar_tag{}); } template<typename T> Pointer<T> make_array(T* ptr) { return Pointer<T>(ptr, array_tag{}); }
关键注意事项
- 务必保证分配方式与释放方式严格匹配:
new对应delete,new[]对应delete[],否则会触发未定义行为。上述方案的核心就是将分配和释放的逻辑绑定,避免用户手动出错。 - 如果需要支持数组的
operator[],可以在类中添加条件重载,或者参考标准库std::unique_ptr<T[]>的模板特化方案实现更彻底的区分。
内容的提问来源于stack exchange,提问作者user21907176
相关产品推荐
相关产品推荐

