Lambda:为什么是通过值const捕获,而不是通过引用值捕获
Lambda: Why are captured-by-value values const, but capture-by-reference values not?
为什么由值const捕获,而不是由引用对象捕获:
int a;
auto compile_error = [=]()
{
a = 1;
}
auto compiles_ok = [&]()
{
a = 1;
}
对我来说,这似乎不合逻辑,但这似乎是标准?特别是对捕获的值进行不必要的修改可能是一个令人讨厌的错误,但后果很可能仅限于lambda范围,而对通过引用捕获的对象进行不必要修改通常会导致更严重的影响。
那么,为什么不默认通过const引用进行捕获呢?或者至少支持[cons&]和[&'?这种设计的原因是什么?
作为解决方法,您可能应该使用由value捕获的std::cref包装的const引用?
假设您正在按值捕获指针。指针本身是常量,但对它所指向的对象的访问不是常量。
int i = 0;
int* p = &i;
auto l = [=]{ ++*p; };
l();
std::cout << i << std::endl; // outputs 1
此lambda相当于:
struct lambda {
int* p;
lambda(int* p_) : p(p_) {}
void operator()() const { ++*p; }
};
operator()()
上的const
使用p
相当于将其声明为:
int* const p;
引用也会发生类似的事情。引用本身是"const"(用引号括起来,因为引用无法重新密封(,但对其引用的对象的访问不是。
捕获的引用也是const
。或者更确切地说,引用总是隐含的const
——语言中没有语法允许您更改引用指向的位置。当a
是引用时,a = 1;
不是更改引用,而是更改引用引用的内容。
当你谈到"const reference"时,我想你会感到困惑。您所说的是"对const int的引用"(const int &
(。那里的"const"指的是引用所指向的东西,而不是引用本身。这与指针类似:使用"pointer to const int"(const int *
(,指针本身不是const
——您可以随心所欲地将其分配给这种类型的变量。真正的"常量指针"应该是int *const
。在这里,你不能分配给这种类型的东西;但是你可以修改它指向的int
。因此,指针或引用的"const"与它指向的东西的"const"是分开的。你也可以有一个"const pointer to const int":const int *const
。
我的逻辑如下:lambdas只是一段代码,具有可选的必需引用。在需要实际复制某些内容的情况下(通常出于内存管理目的,例如复制shared_ptr(,您仍然不希望lambda有自己的状态。这种情况很不寻常。
我认为只有以下两个选项感觉"正确">
- 使用一些局部变量封装一些代码,这样您就可以"传递它">
- 和上面一样,只添加内存管理,因为也许你想异步执行这段代码,那么创建范围就会消失
但是,当lambda是"可变的"时,即它捕获的值不是常量,这意味着它实际上支持自己的状态。也就是说,每次调用lambda时,它都可能产生不同的结果,这不是基于其实际的闭包,而是基于其内部状态。考虑到lambda起源于函数式语言,这在我的书中有点违反直觉。
然而,作为C++,C++给了你一种绕过这种限制的方法,它也让它变得更丑陋,只是为了确保你意识到你在做一些奇怪的事情。
我希望这是你的理由。
- 在 const 函数中通过引用和指针返回之间的区别
- 使用对const结构的const数组的引用进行构造
- 将const引用参数初始化为默认参数会导致悬空引用吗
- 在C++17中,引用const字符串的语义应该是什么
- 为什么当我为 for(auto& it : myUnorderedMap) {... = std::move(it.second)} 时,我会得到一个 const 引用?
- 类型为 "Bucket&"(未限定的 const 限定)的引用不能使用 "SortedList." 类型的值进行初始化 如何修复此错误?
- 为什么在引用指针时将 const 放在 & 符号的左侧有效,而在右侧则无效?
- 将返回类型专用化为 void 或 const 左值引用
- 在其他容器中使用 boost::container::static_vector 时,GCC 编译错误"将'const s'绑定到类型's&'的引用丢弃限定符"
- 在 C++ 中通过引用传递类成员时,Const 不起作用
- 我们可以有一个 setter 成员函数作为从 const 对象引用的 const 吗?
- 将对象传递给函数而不将其包装到 std::ref 中,而参数被指定为 const 引用
- 错误:对类型 'const ItemInstance' 的引用无法绑定到类型 'void' 的右值
- 包括"lvtocon.h",未定义对'operator<<(std::ostream&, char const*)的引用
- 如何在构造函数中传递 const 引用时强制编译器不接受右值
- 通过使用 const-cast 的非常量引用来延长临时的寿命
- const TYPE&- 我什么时候想通过引用 const 来使用?
- 指针引用const null值
- 三元运算符和通过引用const延长临时对象的生存期
- 为什么必须引用const来避免复制形参?