[英]How can I capture the element in a vector in C++ Lambda?
I initialized an instance with a Lambda in it which the Lambda can modify the instance state through capturing the instance by reference.我用 Lambda 初始化了一个实例,其中 Lambda 可以通过引用捕获实例来修改实例 state。 When I put the instance in a vector and invoke the Lambda, the Lambda modifies the original initialized instance not the instance in the vector.
当我将实例放入向量中并调用 Lambda 时,Lambda 会修改原始初始化实例而不是向量中的实例。
#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
*/
}
Thank you all very much.非常感谢大家。 This helps me a lot to understand what's going on here and how to fix it.
这有助于我了解这里发生了什么以及如何解决它。
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;
}
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;
}
Accroding to @Caleth, I did not try to modify the original instance again, feel free to try youself if you are still interested in referring each other method.根据@Caleth,我没有尝试再次修改原始实例,如果您仍然有兴趣互相引用方法,请自行尝试。
When I put the instance in a vector
当我将实例放入向量中时
You can't do that.你不能那样做。 You can copy the instance into a vector element.
您可以将实例复制到矢量元素中。 In C++ an object is the memory it occupies.
在 C++ 和 object是它占据的 memory。
Can I modify the container instance state by the Lambda capturing the original reference and vice versa?
我可以通过捕获原始引用的 Lambda 来修改容器实例 state,反之亦然?
Because they are separate objects, they would need some way of referring to each other, such as a BoolState * other
member.因为它们是独立的对象,所以它们需要某种相互引用的方式,例如
BoolState * other
成员。
Emplacing an element into a container does construct the element in place.将元素放置到容器中确实会在适当位置构造元素。 The constructor is called with the parameters provided by you.
使用您提供的参数调用构造函数。 It helps to avoid creating an unnecessary instance when all you need is to copy/move it into the container.
当您只需将其复制/移动到容器中时,它有助于避免创建不必要的实例。
However, if you do have an instance already, then emplacing an element is not much different from pushing it: The parameter is used to call the copy constructor and you end up with a copy in the container.但是,如果您确实已经有一个实例,那么放置一个元素与推送它并没有太大区别:该参数用于调用复制构造函数,您最终会在容器中获得一个副本。
Terminology is perhaps a little misleading, because you can never first create an object and then place that object in a container.术语可能有点误导,因为您永远不能先创建 object,然后将 object 放入容器中。 Consider the simple case of a c-array:
考虑一个 c 数组的简单情况:
int x;
int a[3];
There is no way to have &x == &a[0]
, ie an element inside the container can be equal, but not identical to an element outside.没有办法拥有
&x == &a[0]
,即容器内的元素可以相等,但与外面的元素不同。 Of course you can emulate it with a level of indirection (eg pointers).当然,您可以使用一定程度的间接(例如指针)来模拟它。
Here's the real minimal example:这是真正的最小示例:
#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
Vectors own their contents.向量拥有它们的内容。 They do that by copying what you give them.
他们通过复制你给他们的东西来做到这一点。
Your object in main
is not the same object that's in the vector.您在
main
中的 object 与向量中的 object 不同。 Modifying one will not modify the other.修改一个不会修改另一个。
That doesn't mean you can't do what you want, but you'll have to give the object that's in the vector a name in order to capture it:这并不意味着你不能做你想做的事,但你必须给向量中的 object 一个名字才能捕获它:
BoolState& bsInVector = bss.at(0);
auto func = [&bsInVector]() { /* ... */ };
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.