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

如何禁止向自定义observer_ptr构造函数传入new T?

如何禁止observer_ptr直接接收new T的结果

要禁止observer_ptr<T> var_name(new T);这类违背设计初衷的用法,核心是通过构造函数的重载和删除,阻止右值原始指针(比如new T的返回值)被传入构造函数。下面是具体实现思路和代码示例:

核心思路

new T返回的是右值类型的原始指针(T*&&),我们可以通过两种方式限制:

  • 删除接受右值原始指针的构造函数,同时保留接受左值原始指针的版本——强制用户先将原始指针存入左值变量,明确所有权归属自己;
  • 仅提供从智能指针(std::unique_ptr/std::shared_ptr)构造的接口,彻底杜绝直接传入原始指针的可能(适合完全不想处理原始指针的场景)。

实现示例

方案1:限制右值原始指针,允许左值和智能指针构造

#include <memory>

template <typename T>
class observer_ptr {
public:
    // 允许从左值原始指针构造(用户需自行管理该指针的生命周期)
    explicit observer_ptr(T*& ptr) : m_ptr(ptr) {}

    // 允许从智能指针构造(明确所有权由智能指针持有)
    explicit observer_ptr(const std::unique_ptr<T>& smart_ptr) 
        : m_ptr(smart_ptr.get()) {}
    explicit observer_ptr(const std::shared_ptr<T>& smart_ptr) 
        : m_ptr(smart_ptr.get()) {}

    // 支持空指针
    observer_ptr(std::nullptr_t) noexcept : m_ptr(nullptr) {}

    // 禁止从右值原始指针构造(直接传入new T会触发编译错误)
    observer_ptr(T*&&) = delete;

    // 必要的成员函数
    T& operator*() const { return *m_ptr; }
    T* operator->() const { return m_ptr; }
    T* get() const { return m_ptr; }

private:
    T* m_ptr;
};

这样编写后,以下用法会编译失败:

// 错误:尝试将右值指针传入已删除的构造函数
observer_ptr<int> p(new int(42));

而合法的用法包括:

// 合法:先将原始指针存入左值,用户自行管理所有权
int* raw = new int(42);
observer_ptr<int> p(raw);

// 合法:从unique_ptr构造,所有权由unique_ptr持有
auto uptr = std::make_unique<int>(42);
observer_ptr<int> p2(uptr);

// 合法:空指针
observer_ptr<int> p3(nullptr);

方案2:仅允许从智能指针构造

如果完全不想处理原始指针,可以只保留智能指针的构造函数,删除所有原始指针相关的构造函数:

template <typename T>
class observer_ptr {
public:
    explicit observer_ptr(const std::unique_ptr<T>& smart_ptr) 
        : m_ptr(smart_ptr.get()) {}
    explicit observer_ptr(const std::shared_ptr<T>& smart_ptr) 
        : m_ptr(smart_ptr.get()) {}

    observer_ptr(std::nullptr_t) noexcept : m_ptr(nullptr) {}

    // 删除所有原始指针相关的构造函数
    observer_ptr(T*) = delete;
    observer_ptr(T*&) = delete;
    observer_ptr(T*&&) = delete;

    // 成员函数同方案1...

private:
    T* m_ptr;
};

这种方案下,用户只能从智能指针或空指针创建observer_ptr,彻底避免了手动管理原始指针的风险。

原理说明

C++中,new T的结果是一个临时的右值指针,无法绑定到非const的左值引用(T*&),同时我们显式删除了接受T*&&的构造函数,因此编译器会直接拒绝observer_ptr<T>(new T)这类调用,从语法层面阻止了违背设计初衷的用法。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 17:08:18