在lambda [C ]中捕获这一点的替代方法

Alternative to capture this in lambda [C++]

本文关键字:这一点 方法 lambda      更新时间:2023-10-16

我知道我是否必须在lambda中调用成员函数进行回调,我会在lambda中捕获此功能,而且效果很好。但是我最近看到了一些崩溃,看来对象指向的对象已经被破坏后访问了成员函数。简而言之,在关闭中,该物体被破坏了,但是指针是在lambda中传递的,lambda被访问并导致崩溃。

所以,我试图了解社区在这种情况下通常会做什么。我找不到太多的东西,但我认为shared_ptr可能是一个选择。

任何建议/潜在客户都将不胜感激,以帮助我理解和实施替代方案。

在C 中,您有责任跟踪对象寿命。

这意味着您必须跟踪持有指针和引用其他事物的事物的寿命,并确保它们不像这些东西那样活。

您的任务失败了。您通过了将指针捕获到周围的对象的lambdas,就像它们在糖果的位置一样,而不是直接进入对象的胆量。

通过在共享指针上撒终身问题通常是一个坏主意。使物体的寿命更加模糊可能会减少立即崩溃的事件,但是含糊的物体寿命球不会使您的程序工作。模糊的球要么扩展以涵盖您的整个程序,现在永远无法实际关闭,要么它自身旋转并自我延续,泄漏了资源。

共享指针可在狭窄的情况下使用,在狭窄情况下,您拥有定义的终身关系,最好将其建模为共享所有权。这与"我的对象在指针之前要走了,所以我应该尝试共享指针!"您有一个对象寿命问题。您尝试共享指针。现在您有两个问题:原始对象寿命问题和您的共享指针问题。

回调是您需要严格终身规则的情况的一个示例。您回调多长时间?你什么时候停下来?您如何紧急回收资源?您如何取消回调?等。

我写了使用共享和弱指针的回调系统。他们不是完美的。这是我在Google:Broadcaster中发现的。听众存储代币说"不断跟我说话",当他们走开时,广播公司停止撒谎。

这是我用于处理订阅的模式。锁定weak_ptr的使用消除了交叉案例的风险。

#include <memory>
#include <chrono>
#include <thread>
#include <mutex>
using namespace std::literals;
// some external service that will send us events in a callback.
// normally of course we'd have some means to turn these off too.
// However for this demo we'll ignore that for now
void subscribe_for_events(std::function<void()> f);
struct might_go_away : std::enable_shared_from_this<might_go_away>
{
    static std::shared_ptr<might_go_away> create() {
        auto p = std::make_shared<might_go_away>();
        p->start();
    }
    might_go_away() {}
private: 
    using mutex_type = std::mutex;
    using lock_type = std::unique_lock<mutex_type>;
    // handy helper to deliver a weak pointer to ourselves
    auto weak_self() { return std::weak_ptr<might_go_away>(shared_from_this()); }
    // do startup things here, like subscribing to other services etc
    void start() {
        subscribe_for_events([this, weak = this->weak_self()]
        {
            // don't touch 'this' until we have successfully locked the weak ptr
            if (auto self = weak.lock()) {
                // we know we're alive. the variable 'self' will hold the strong count > 0
                // this is a good place to take locks
                handle_event(lock_type(mutex_));
            }
        });
    }
    void handle_event(lock_type) {
        // do things when notified by some event source.
        // we are safe here. `this` will not go away and we own the mutex 
        // we will release the lock when this function exits through RAII.
        // PLUS, because the lock was moved in, we own it. We can release it early if we wish.
    }
    mutex_type mutex_;
};

当然,在生产代码中,shared_ptr将包裹在面向消费者的手柄类中。

我们更喜欢在可能的情况下进行价值语义。

struct active_thing
{
    using implementation_class = might_go_away;
    using implementation_type = std::shared_ptr<implementation_class>;
    active_thing() : impl_(implementation_class::create()) {}
    // methods here
private:
    implementation_type impl_;
};

int main()
{
  {
    auto a = active_thing();
    std::this_thread::sleep_for(5s);
  }
}
相关文章: