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

C++实现非C++11版unique_ptr时如何区分指针由new还是new[]分配

首先明确一个核心结论:不存在可移植的标准方法能够仅通过一个裸指针的值判断它是通过new还是new[]分配的。C++标准没有规定裸指针需要携带分配方式相关的元信息,不同编译器的堆内存布局实现属于未公开的私有细节,依赖这类细节的实现不具备可移植性,也不符合学校作业的规范要求。

你可以通过以下两种符合C03标准的方案解决这个问题,不需要用到C11的default_delete特性:

方案1:模板偏特化(推荐,和标准库实现逻辑一致)

标准库本身的unique_ptr就没有尝试从指针判断分配方式,而是通过两个不同的模板特化来区分单对象和数组场景,这个逻辑完全可以在C++03下实现:

  1. 主模板处理单个对象分配场景,析构调用delete
template <typename T>
class unique_ptr {
private:
    T* ptr_;
    // C++03下禁止拷贝语义,将拷贝构造和拷贝赋值声明为私有不实现
    unique_ptr(const unique_ptr&);
    unique_ptr& operator=(const unique_ptr&);
public:
    explicit unique_ptr(T* p = 0) : ptr_(p) {}
    ~unique_ptr() {
        delete ptr_;
    }
    // 其他必要接口实现
    T* release() {
        T* tmp = ptr_;
        ptr_ = 0;
        return tmp;
    }
    void reset(T* p = 0) {
        if (ptr_ != p) {
            delete ptr_;
            ptr_ = p;
        }
    }
    T& operator*() const { return *ptr_; }
    T* operator->() const { return ptr_; }
};
  1. 偏特化版本处理数组分配场景,析构调用delete[]
template <typename T>
class unique_ptr<T[]> {
private:
    T* ptr_;
    unique_ptr(const unique_ptr&);
    unique_ptr& operator=(const unique_ptr&);
public:
    explicit unique_ptr(T* p = 0) : ptr_(p) {}
    ~unique_ptr() {
        delete[] ptr_;
    }
    // 数组版本额外提供下标访问重载
    T& operator[](size_t idx) const { return ptr_[idx]; }
    // 其他通用接口实现
    T* release() {
        T* tmp = ptr_;
        ptr_ = 0;
        return tmp;
    }
    void reset(T* p = 0) {
        if (ptr_ != p) {
            delete[] ptr_;
            ptr_ = p;
        }
    }
};

使用时通过显式指定模板参数区分场景即可:

  • 单对象分配:unique_ptr<int> ptr(new int(5));
  • 数组分配:unique_ptr<int[]> ptr(new int[10]);

你示例中unique_ptr<int> ptr(new int[10]);本身就是错误用法,哪怕是标准库的unique_ptr这么写也会触发未定义行为,这类问题属于用户使用错误,不需要你的实现兜底。

方案2:构造时传入分配类型标记

如果你的需求必须让同一个模板实例同时支持两种分配方式,可以在构造函数中新增一个标记参数,由调用方手动指定分配类型:

enum AllocType {
    SINGLE_ALLOC, // 对应new分配
    ARRAY_ALLOC   // 对应new[]分配
};
template <typename T>
class unique_ptr {
private:
    T* ptr_;
    AllocType alloc_type_;
    unique_ptr(const unique_ptr&);
    unique_ptr& operator=(const unique_ptr&);
public:
    unique_ptr(T* p, AllocType type = SINGLE_ALLOC) : ptr_(p), alloc_type_(type) {}
    ~unique_ptr() {
        if (alloc_type_ == SINGLE_ALLOC) {
            delete ptr_;
        } else {
            delete[] ptr_;
        }
    }
    // 其他接口实现省略
};

这种方案的缺点是依赖调用方手动传入正确的标记,出错概率比模板特化方案高,仅在特殊场景下使用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 13:45:03