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

如何确保std::weak_ptr不由临时std::shared_ptr创建?编译时限制use_weak_ptr方法参数的方案问询

解决方案:编译期限制use_weak_ptr仅接受左值std::shared_ptr

这个问题很实用——毕竟把临时std::shared_ptr转成weak_ptr后,临时对象会立刻销毁,对应的weak_ptr直接变成空悬状态,完全达不到预期用途。下面给你两种编译期就能阻止这种错误的方案,简单直接且高效:

方法1:删除右值引用版本的重载

最直观的方式是为use_weak_ptr提供两个重载:一个接受左值引用的std::shared_ptr<Foo>(正常使用),另一个接受右值引用的版本并显式删除它。编译器会在遇到临时对象(右值)时匹配到被删除的重载,直接抛出编译错误。

#include <memory>

class Foo {};

// 允许传入左值std::shared_ptr<Foo>
void use_weak_ptr(const std::shared_ptr<Foo>& sp) {
    std::weak_ptr<Foo> wp = sp;
    // 在这里执行你的业务逻辑
}

// 明确禁止传入右值(临时对象)
void use_weak_ptr(std::shared_ptr<Foo>&&) = delete;

验证调用场景

  • ✅ 允许的调用(左值传入):
    auto shared = std::make_shared<Foo>();
    use_weak_ptr(shared); // 编译通过,匹配左值引用版本
    
  • ❌ 禁止的调用(临时对象传入):
    use_weak_ptr(std::make_shared<Foo>()); // 编译错误:尝试调用已删除的函数
    

方法2:用模板+类型约束实现更严格的检查

如果你想要更灵活的模板化方案,也可以借助std::is_lvalue_reference和SFINAE机制,强制要求参数必须是左值引用,同时约束类型为std::shared_ptr<Foo>:

#include <memory>
#include <type_traits>

class Foo {};

template <typename T, typename = std::enable_if_t<std::is_lvalue_reference_v<T>>>
void use_weak_ptr(T&& sp) {
    // 额外的类型检查:确保传入的是std::shared_ptr<Foo>
    static_assert(std::is_same_v<std::decay_t<T>, std::shared_ptr<Foo>>,
                  "use_weak_ptr only accepts lvalue std::shared_ptr<Foo>");
    std::weak_ptr<Foo> wp = sp;
    // 业务逻辑
}

这种方案的好处是可以在编译期给出更明确的错误提示(通过static_assert),帮助开发者快速定位问题。

核心原理

两种方案都是利用C++的重载解析规则:临时对象属于右值,会优先匹配右值引用的函数;当我们删除该重载或通过模板约束排除右值时,编译器就会直接报错,从根源上阻止无效调用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.27 20:14:08