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

C++中如何不使用裸指针实现非拥有式资源视图?

C++中非拥有式资源视图的实现方式

在C++里,要明确建模非拥有式资源视图,有几种标准机制和通用惯用手法可以替代语义模糊的裸指针:

  • 使用C++20引入的std::observer_ptr
    这是标准库专门为非拥有式指针设计的类型,语义上明确表示“仅观察资源,不承担所有权”。它可以从裸指针、std::unique_ptr或std::shared_ptr隐式转换而来,行为和裸指针类似,但禁止通过它执行delete操作,从根源上避免了所有权混淆的问题。示例:

    #include <memory>
    #include <observer_ptr>
    
    void observe_widget(std::observer_ptr<Widget> widget_view) {
        if (widget_view) {
            widget_view->do_something();
        }
    }
    
    int main() {
        auto owned_widget = std::make_unique<Widget>();
        observe_widget(owned_widget); // 隐式转换为observer_ptr
        return 0;
    }
    
  • 使用引用(&)
    如果能确保被观察的资源不会为空,且其生命周期严格长于观察者的生命周期,直接使用引用是最简洁的方案。引用的语义天然就是非拥有式的,不存在空指针风险,代码可读性也极高。示例:

    void update_widget(Widget& widget_ref) {
        widget_ref.update_state();
    }
    
    int main() {
        Widget my_widget;
        update_widget(my_widget);
        return 0;
    }
    
  • 自定义非拥有式观察器类型
    可以自行封装一个轻量级的观察器类,内部持有裸指针,但只暴露访问资源的接口,完全屏蔽所有权相关操作(比如禁止delete、禁止移动语义等),以此明确语义。示例:

    template<typename T>
    class WidgetObserver {
    public:
        explicit WidgetObserver(T* ptr) : ptr_(ptr) {}
        // 仅提供访问接口
        T& operator*() const { return *ptr_; }
        T* operator->() const { return ptr_; }
        explicit operator bool() const { return ptr_ != nullptr; }
    
        // 禁止所有权转移相关操作
        WidgetObserver(const WidgetObserver&) = default;
        WidgetObserver& operator=(const WidgetObserver&) = default;
        WidgetObserver(WidgetObserver&&) = delete;
        WidgetObserver& operator=(WidgetObserver&&) = delete;
    
    private:
        T* ptr_;
    };
    
  • 语义明确的命名约定
    如果不得不使用裸指针(比如兼容旧代码),可以通过命名来明确其非拥有式语义,比如给变量加上_view、_observer后缀,比如Widget* widget_view;。这种方式依赖团队代码规范,但能让其他开发者一眼识别出这只是资源视图,不会用于所有权操作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 20:42:44