微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

C++:将 shared_ptr 传递给 lambda 的有效方法

如何解决C++:将 shared_ptr 传递给 lambda 的有效方法

我几年前创建了一个小程序,最近我开始使用智能指针。因此,出于实践原因,我根据 Scott Meyers - Effective Modern C++ 一书重构了部分代码

想象一个类,它持有另一个类的成员 shared_ptr,管理其他一些不必要的对象的生命周期。

class Foo {
...
    std::shared_ptr<Bar> manager;

    void DoSomeWork();
}

DoSomeWork 方法的实现包含一个 lambda collectIfNeighbor,因为它在某些部分经常使用,这是实现正确行为的最简单方法。主要思想是仅捕获 lambda 中需要的内容,并使用智能指针而不是无处不在的 nullptr 检查。

void Foo::DoSomeWork(){
    std::vector<Object*> neighbors;
    auto collectIfNeighbor = [this,&neighbors](const Position& pos) {
        ...    
        if ( *some condition* )
            neighbors.push_back(manager->Getobject(pos));
    };
    collectIfNeighbor(Position(1,1));    // example usage
    ...
}

所以这里的问题是在 lambda 内部我捕获了 this,但我并不真正需要整个,只需要经理。将 shared_ptr 传递给 lambda 的最有效方法是什么?

如果可能,我不想传递整个 this,因为我只使用一个成员。要么我不想创建和销毁大量的 shared_ptrs,因为它会使它变慢。此外,不关心经理是否还活着也不错。

lambda 实现还有其他方法。将 shared_ptr 复制到本地,并通过引用传递它。但是我在本地制作和额外的副本,我害怕每次 lambda 调用时。另一种方法是简单地创建一个常规指针并将其传递给 lambda。

std::shared_ptr<Bar> localManager = manager;
auto lambdaV1= [&localManager,&neighbors](const Position& pos) {
    ...    
    if ( *some condition* )
        neighbors.push_back(manager->Getobject(pos));
};
Bar* localManagerPtr = manager.get();
auto lambdaV2= [&localManagerPtr,&neighbors](const Position& pos) {
    ...    
    if ( *some condition* && manager != nullptr)    // extra check on manager
        neighbors.push_back(manager->Getobject(pos));
};

我检查了 Passing shared_ptr to lambda cause memory leakCapture by universal ref 但它对我没有太大帮助。

解决方法

对于这种情况,我总是建议先弄清楚这个问题:我的 lambda 可以在 this 的生命周期之后合法地被调用吗?如果是这样,捕获 this 将不是这里的方法。一个类似的问题是:我的 lambda 是否允许延长 this 的生命周期?如果是这样,通过 this 的共享指针捕获 shared_from_this 和相应的 this 方法是一种常见方案,但总是具有额外副本的缺点(以及可能的不明确/复杂的生命周期this...)

在您完全清楚这些问题的前提下,并假设在 this 的生命周期之后必须/不能调用 lambda,简单地捕获 this 是最简单和最便宜的正如 NathanOliver 为您提供的附加提示所指出的解决方案,对您的 lambda 的任何调用都需要合法的 this 指针。对于只捕获一个参数,如果没有其他成员或成员方法,则最大_prime 的简单原始指针捕获解决方案有时会更明确或至少更清晰(不是像 this-capture 这样的锤子)需要在 lambda 的主体内,即 lambda 的工作在语义上与您的实际类有些分离,并且可能会在其他地方进一步使用,因为您的类不是设计的上下文的一部分。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。