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

C++ 如何将std::shared_ptr管理对象的原始this指针转为shared_ptr使用

解决方案

以下是两种适配你需求的常用实现方案,可根据你的业务对生命周期安全和性能的要求选择:

方案1:保留裸指针存储(性能最优,适合生命周期可控场景)

该方案改动最小、无额外性能开销,只要你能保证所有Intersection实例的使用周期,都短于存储对象的world vector的生命周期即可使用:

  • 第一步:让IHittable公共继承std::enable_shared_from_this<IHittable>,示例代码:
class IHittable : public std::enable_shared_from_this<IHittable> {
public:
    virtual Intersection intersects(const Ray& ray) const = 0;
    virtual ~IHittable() = default;
};
  • 第二步:给Intersection新增支持std::shared_ptr<IHittable>的构造函数,满足你要求的调用写法:
class Intersection
{
public:
    Intersection(double t, IHittable * object) : t_(t), object_(object) {}
    // 新增构造函数,支持直接传入shared_ptr构造
    Intersection(double t, const std::shared_ptr<IHittable>& object) : t_(t), object_(object.get()) {}
    [[nodiscard]] double t() const { return t_; }
    [[nodiscard]] IHittable * object() const { return object_; }
private:
    double t_;
    IHittable * object_ = nullptr;
};
  • 第三步:派生类的intersects方法可以直接用this构造返回,原有代码不需要修改;如果想要更统一的写法,也可以用shared_from_this().get()替代this,效果完全一致。

如果你的场景里world会在程序运行全程存在,直到所有求交计算结束才销毁,该方案是最优选择,遍历world调用intersects的效率和裸指针vector完全一致。

方案2:Intersection存储shared_ptr(生命周期安全,适合复杂场景)

如果你的业务逻辑中存在world可能提前释放,或者Intersection需要脱离world长期留存的场景,可以把Intersection内部的存储改成shared_ptr,完全避免悬空指针问题:

  • 第一步:同样让IHittable继承std::enable_shared_from_this<IHittable>
  • 第二步:修改Intersection的定义:
class Intersection
{
public:
    Intersection(double t, std::shared_ptr<IHittable> object) : t_(t), object_(std::move(object)) {}
    [[nodiscard]] double t() const { return t_; }
    // 可根据需要返回裸指针或者shared_ptr的常量引用
    [[nodiscard]] IHittable * object() const { return object_.get(); }
    [[nodiscard]] const std::shared_ptr<IHittable>& shared_object() const { return object_; }
private:
    double t_;
    std::shared_ptr<IHittable> object_ = nullptr;
};
  • 第三步:修改派生类的intersects返回逻辑:
Intersection Sphere::intersects(const Ray & ray)
{
    double x = ...; // 原有求交计算逻辑不需要改动
    return {x, shared_from_this()};
}

该方案的优势是完全不需要操心生命周期问题,只要Intersection还存在,对应的Hittable对象就不会被释放,唯一的额外开销是shared_ptr的引用计数增减,对于绝大多数图形学场景来说这点性能损失可以忽略不计。

注意:使用std::enable_shared_from_this的前提是,所有IHittable的实例都必须由std::shared_ptr管理,不能在栈上分配IHittable的派生类实例,也不能用裸指针创建的实例调用shared_from_this(),否则会触发未定义行为。你的场景里所有对象都通过std::make_shared创建并存入world vector,完全符合这个要求,不会有问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 12:48:02