如何防止删除用作共享指针的原始指针?

How to prevent deletion of a raw pointer that is used as shared pointer?

我为 C++ class 实现了 C-API,它使用其他对象的共享指针来访问它们。 在我的 C-API 中,我当然只能得到原始指针。 所以我 "convert" 我的 C-API 中的原始指针指向共享指针,然后将其与我的 C++ class 方法一起使用:

method(std::shared_ptr<dataType>(raw-pointer));

现在我遇到的问题是在 "method" 结束时总是调用共享指针析构函数,不幸的是它杀死了我的原始指针指向的对象(我不想要)。 那么,如何防止原始指针被杀死?

我已经尝试过像 reset() 或 swap() 这样的共享指针函数,但它们都没有让我的原始指针消失...

bool Traffic_doStep(traffic_handle t, environment_handle e, double cycletime) {
    if (!valid(t, __FUNCTION__)) return false;
    if (!valid(e, __FUNCTION__)) return false;
    if (!valid(cycletime, __FUNCTION__)) return false;

    try {
        t->doStep(std::shared_ptr<Environment>(e), cycletime);
        return true;
    }
    catch (const std::exception& e) {
        std::cerr << e.what() << std::endl;
        return false;
    }
}

预期结果是原始指针 e 在此函数返回后仍指向有效对象。 实际上,原始指针然后指向一个已删除的对象。

不要把指针放在std::shared_ptr

C++ 中智能指针的目的是提供自动生命周期管理。当你写 std::shared_ptr<int> ptr{raw_ptr}; 时,期望的是当 ptr 超出范围时,raw_ptr 指向的对象将是 delete'。如果这不是本意,那么您不应该将指针放在智能指针中。

因此,如果您的应用程序不管理指针的生命周期,那么存储原始指针是完全可以接受的。

如果函数后面的API不能改变,你需要构造一个空操作删除函数的std::shared_ptr,这样当clean-up被调用时,什么都不会发生在指针上。

try {
    std::shared_ptr<Environment> temp_ptr{e, [](int *) {}/*No-Op Deleter*/};
    t->doStep(temp_ptr, cycletime);
    return true;
}

这将解决您的问题,但这当然是一个反模式;不要这样做,除非你被 API 你无法控制的设计限制所迫。

您可以提供共享指针的自定义删除器。

这是一个可行的构造函数:

template< class Y, class Deleter > 
shared_ptr( Y* ptr, Deleter d );

但我宁愿使用一个唯一的指针,然后释放它。