Imm*_*ant 2 c++ lambda copy this capture
请参阅此线程:https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0806r2.html
它说:
换句话说,一个默认捕获 ([&]) 以拼写出冗余的方式捕获 *this,但另一个捕获 ([=]) 以非冗余方式捕获它。
这表示在 c++17 之前,[=] 捕获this
为值,而 [&] 将捕获 [*this],这是不明确的。所以我进行了一个快速测试,看看 [&] 是否默认捕获 [*this]。
我的测试代码尝试查看 [&] 默认捕获 *this,然后应该调用复制构造函数,并且对其值的任何更改都不会影响原始对象,因为它是副本。
#include<iostream>
using namespace std;
class M{
int mI;
public:
M() : mI(3) { cout << "ctor\n"; }
~M() { cout << "dtor\n"; }
M(const M& m) {
if (this != &m) {
cout << "copy ctor\n";
mI = m.mI;
}
}
M& operator=(const M& m) {
if (this != &m) {
cout << "operator =\n";
mI = m.mI;
}
return *this;
}
void CaptureByValue() {
auto f1 = [=] () { // capture this
cout << mI << '\n';
++(this->mI);
};
f1();
cout << mI << '\n';
}
void CaptureByReference() {
auto f1 = [&] () { // capture *this
cout << mI << '\n';
++(this->mI);
};
f1();
cout << mI << '\n';
}
};
int main() {
{
M obj1;
obj1.CaptureByValue();
}
cout << "------------\n";
{
M obj2;
obj2.CaptureByReference();
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
编译并运行它:
clang++ LambdaCapture.cpp -std=c++11 && ./a.out
clang++ LambdaCapture.cpp -std=c++14 && ./a.out
clang++ LambdaCapture.cpp -std=c++17 && ./a.out
Run Code Online (Sandbox Code Playgroud)
所有案例打印:
ctor
3
4
dtor
------------
ctor
3
4
dtor
Run Code Online (Sandbox Code Playgroud)
我的问题:
(1)结果超出了我的预期:没有调用任何复制构造函数CaptureByReference
,并且更改的值影响了原始this
对象。测试代码没有促进 cpp17 中的 lambda 语法更改。
(2) 我什至无法将捕获更改为 [=, *this] 或 [&, *this],因为编译器会说:
LambdaCapture.cpp:25:13: error: read-only variable is not assignable
++(this->mI);
^ ~~~~~~~~~~
Run Code Online (Sandbox Code Playgroud)
很奇怪,这里怎么出来一个read-only
变量,至于this
指针。
感谢您的解释。
[=]
、[this]
、[=, this]
以及所有按值[&, this]
捕获。this
也就是说,它复制了指针的值this
。[&]
*this
通过引用捕获。也就是说,this
在 lambda 中是一个指向*this
lambda 外部的指针。this
因此,上述版本在 lambda 中的效果是相同的。
[=, *this]
复制捕获的所有元素,并复制*this
- 而不是this
指针。[&, *this]
引用所有捕获的元素,但复制*this
.LambdaCapture.cpp:25:13: error: read-only variable is not assignable
++(this->mI);
^ ~~~~~~~~~~
Run Code Online (Sandbox Code Playgroud)
这是因为 lambda 是const
默认的。你需要创造它们mutable
才能改变它们。
auto f1 = [&, *this]() mutable { // made mutable
cout << mI << '\n';
++(this->mI); // now ok
};
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
557 次 |
最近记录: |