c++ - 如何在C++ Lambda中捕获 vector 中的元素?

标签 c++ lambda capture

场景:
我用Lambda初始化了一个实例,其中Lambda可以通过按引用捕获实例来修改实例状态。
当我将实例放入 vector 中并调用Lambda时,Lambda会修改原始初始化的实例,而不是 vector 中的实例。
最小的C++程序来说明:

#include <iostream>
#include <functional>
#include <vector>

struct BoolState {
    bool _stateChangeByInstanceReference = false;
    bool _stateChangeByContainerReference = false;
    std::function<void()> _changeStateByInstanceReference;
    std::function<void()> _changeStateByContainerReference;
};

int main()
{
    using namespace std;
    vector<BoolState> bss;
    BoolState bs;
    bs._changeStateByInstanceReference = [&bs]() -> void { bs._stateChangeByInstanceReference = true; };
    bs._changeStateByContainerReference = [&bss]() -> void { bss.at(0)._stateChangeByContainerReference = true; };
    bss.emplace_back(bs);
    bss.back()._changeStateByInstanceReference();
    bss.back()._changeStateByContainerReference();
    cout << "The original instance by instance reference: " << bs._stateChangeByInstanceReference << endl;
    cout << "The original instance by container reference? " << bs._stateChangeByContainerReference << endl;
    cout << "The container instance by instance reference? " << bss.back()._stateChangeByInstanceReference << endl;
    cout << "The container instance by container reference: " << bss.back()._stateChangeByContainerReference << endl;
    /*
        The original instance by instance reference: 1
        The original instance by container reference? 0
        The container instance by instance reference? 0
        The container instance by container reference: 1
    */
}
题:
  • 由于我是在Lambda中通过引用捕获实例的,因此
    原始初始化实例和vector中的实例均为2
    不同的实例? (我可以打印出这2个实例在内存中有2个不同的地址,但我不明白:为什么是这种情况?这将如何影响结果?)
  • 是否可以通过Lambda捕获原始引用来修改容器实例状态,反之亦然?

  • 根据@Asteroids With Wings,@ idclev 463035818和@Caleth的解决方案:
    非常感谢大家!这对我很有帮助,可以了解这里发生的情况以及如何解决它。
    根据@Asteroids With Wings的push_back()版本:
    int main()
    {
        using namespace std;
        vector<BoolState> bss;
        BoolState bs;
        bs._changeStateByContainerReference = [&bss]() -> void { bss.at(0)._stateChangeByContainerReference = true; };
        // Only copy container version Lambda
        bss.push_back(bs);
        // Modify in place with instance version Lambda
        BoolState& bsInbss = bss.at(0);
        bss.at(0)._changeStateByInstanceReference = [&bsInbss]() -> void { bsInbss._stateChangeByInstanceReference = true; };
        bss.at(0)._changeStateByInstanceReference();
        bss.at(0)._changeStateByContainerReference();
        cout << "The container instance by instance reference:(solved) " << bss.back()._stateChangeByInstanceReference << endl;
        cout << "The container instance by container reference: " << bss.back()._stateChangeByContainerReference << endl;
    }
    
    @idclev 463035818的“真实” emplace_back()版本
    int main() {
        using namespace std;
        vector<BoolState> bss;
        bss.emplace_back(BoolState());
        BoolState& bsInbss = bss.at(0);
        bss.at(0)._changeStateByInstanceReference = [&bsInbss]() -> void { bsInbss._stateChangeByInstanceReference = true; };
        bss.at(0)._changeStateByContainerReference = [&bss]() -> void { bss.at(0)._stateChangeByContainerReference = true; };
        bss.at(0)._changeStateByInstanceReference();
        bss.at(0)._changeStateByContainerReference();
        cout << "The container instance by instance reference:(solved) " << bss.back()._stateChangeByInstanceReference << endl;
        cout << "The container instance by container reference: " << bss.back()._stateChangeByContainerReference << endl;
    }
    
    感谢@Caleth,我没有尝试再次修改原始实例,如果您仍然对互相引用的方法感兴趣,请尝试一下。

    最佳答案

    这是真正的最小示例😉:

    #include <iostream>
    #include <vector>
    
    int main()
    {
        std::vector<int> v;
        
        int x = 42;
        v.emplace_back(x);
        
        std::cout << &x << '\n';
        std::cout << &v[0] << '\n';
    }
    
    // 0x7ffd008d9d14
    // 0x1f7fc20
    
    
    (live demo)
    vector 拥有其内容。他们通过复制您给他们的东西来做到这一点。main中的对象与 vector 中的对象不同。修改一个不会修改另一个。
    这并不意味着您不能做您想做的事,但是您必须给 vector 中的对象起一个名字才能捕获它:
    BoolState& bsInVector = bss.at(0);
    auto func = [&bsInVector]() { /* ... */ };
    

    关于c++ - 如何在C++ Lambda中捕获 vector 中的元素?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63029711/

    相关文章:

    c++ - 将递归模拟为堆栈返回错误

    c++ - 使用预编译器的字符串连接

    c# - 如何阅读这个 lambda 表达式

    c# - IQueryable 扩展 : create lambda expression for querying a column for a keyword

    c++ - Lambda 标识符是如何捕获的?

    c++ - 如何调试丢包?

    c++ - QML 不注册 C++ 属性的属性更改

    c# - 分组依据、计数和 Lambda 表达式

    java - 更快的屏幕捕获方式(java)

    regex - 如何使用量词访问括号中的捕获缓冲区?