我偶尔会想出这样的代码:
// lazy lambda:
[&] {
// use references to a, b, c
}
// pedantic lambda
[&a, &b, &c] {
// use references to a, b, c
}
Run Code Online (Sandbox Code Playgroud)
我想知道根据C++ 14标准(或更高版本)和编译器的实际经验,哪些lambda在性能和可执行大小方面更好.
这个例子没有区别.编译器将仅捕获lambda中显式引用的变量,使得延迟捕获等效于显式捕获.
懒惰捕获稍微方便一些.更改lambda的主体以使用其他捕获的变量,或从现有lambda中删除对捕获的变量的所有引用,通常还需要更新显式捕获列表.通过延迟捕获,编译器将为您完成所有操作.
除了显式捕获 lambda 中根本未提及的内容的小情况之外,还有两种极端情况可能存在差异。
首先,隐式捕获通常不会捕获未使用 odr 的实体(但请参阅下一项以了解例外情况)。除其他外,这包括未计算的操作数中提到的内容,例如 和 的操作数decltype,sizeof以及在某些上下文中使用时的某些变量const和局部变量(请参阅[basic.def.odr]以获取完整的规则集):constexpr
void f(int){}
void f2(const int &) {}
void t() {
const int x = 8;
constexpr double y = 8;
const double z = 8;
auto g = []{ f(x); }; // OK
auto g1 = [=]{ f(x); }; // OK, does not capture x
// usually won't fire, though not guaranteed
static_assert(sizeof(g) == sizeof(g1), "!!");
auto g2 = []{ f(y); }; // OK
auto g3 = []{ f(z); }; // Error, must capture z
auto g4 = []{ f2(x); }; // Error, must capture x since it's odr-used
auto g5 = [=]{ f2(x); }; // OK, captures x
auto g6 = []{ f2(+x); }; // OK, doesn't odr-use x
auto g7 = []{ f2(y); }; // OK
}
Run Code Online (Sandbox Code Playgroud)
如果您手动编写捕获列表,则捕获的数据可能会超出技术上所需的数量,因为管理 ODR 使用或不使用的规则非常复杂。
其次,出于理智考虑,通用 lambda 中的隐式捕获将捕获依赖表达式中使用的内容,即使它们不一定是 odr 使用的。借用标准中的一个例子:
void f(int, const int (&)[2] = {}) { } // #1
void f(const int&, const int (&)[1]) { } // #2
void test() {
const int x = 17;
auto g2 = [=](auto a) {
int selector[sizeof(a) == 1 ? 1 : 2]{};
f(x, selector); // OK: is a dependent expression, so captures x
// Will actually odr-use x only if sizeof(a) == 1
};
}
Run Code Online (Sandbox Code Playgroud)
然而,在编写通用 lambda 时,您实际上并不需要捕获可能会或可能不会使用的东西;仅当您实例化 odr 使用该事物的函数调用运算符的专门化时,才需要捕获它。因此,如果您从不以 odr-use 有问题的方式调用生成的泛型 lambda,那么隐式捕获可能会捕获超过您需要的最小值。例如,这是允许的:
void test() {
const int x = 17;
auto g3 = [](auto a) { // no capture
int selector[sizeof(a) == 1 ? 1 : 2]{};
f(x, selector); // OK for now
};
}
Run Code Online (Sandbox Code Playgroud)
只要您不g3使用大小为 1 的任何内容进行调用:g3(0)在典型系统上就可以;g3('\0')不是。
| 归档时间: |
|
| 查看次数: |
173 次 |
| 最近记录: |