在最近的一个C++ 0x草案(n3225.pdf)中,我们可以找到5.1.2/10:
使用通常的非限定名称查找规则(3.4.1)查找捕获列表中的标识符; 每个这样的查找应该找到一个变量,其自动存储持续时间在本地lambda表达式的到达范围内声明.如果实体(即变量或此实体)出现在lambda表达式的捕获列表中,则称其被明确捕获.
这对我来说似乎相当严格.例如,在我看来,以下事情是不允许的:
int global;
struct s {
int x;
void memfun() {
[x,global]{};
}
};
Run Code Online (Sandbox Code Playgroud)
因为x
不一定是具有自动存储的变量,也不是global
.请注意,此捕捉条款的用意是让拉姆达对象存储复制的x
,并global
可能是可取的情况下,他们在后一阶段发生变化.我已经知道了另一种选择:
int global;
struct s {
int x;
void memfun() {
int copyx = x;
int copyglobal = global;
[copyx,copyglobal]{};
}
};
Run Code Online (Sandbox Code Playgroud)
但这归结为额外的副本和额外的锅炉板只是为了捕获x
和global
复制.
此外,我在最新的草稿中找不到任何结论,如果我们在捕获子句中命名本地引用会发生什么:
int main() {
int i = 0;
int &r = i;
assert([r]{return &r;}() != &i);
}
Run Code Online (Sandbox Code Playgroud)
lambda对象"复制引用"还是"复制int"?如果它通过副本捕获引用的对象,这可以节省我们之前的解决方案中的其他副本.
GCC显然支持所有这些示例,并在最后一种情况下存储一个int的副本(这是可取的,恕我直言).但我想知道这是否实际上是根据C++ 0x草案的预期行为,或者只是一个编译器扩展,分别是一个实现bug.
编辑: …
使用C++ 11 lambda表达式时,如何按值捕获成员变量?
使用[my_member]
语法似乎不起作用,隐式捕获使用this
指针.需要的是一种明确指定成员变量的捕获类型的方法.那可能吗?
我现在的解决方法是:
void member_function()
{
std::shared_ptr<my_member_class> my_member_copy = my_member; // this shouldn't be necessary
std::async([=]{ std::cout << *my_member_copy; });
// std::async([=]{ std::cout << *my_member_; }); // wrong, my member could be potentially out of scope
}
Run Code Online (Sandbox Code Playgroud) 我今天在XCode下对lambdas的这种奇怪行为感到非常痛苦 - 在尝试跟踪iOS中围绕代码的几个内存泄漏之后,我将其缩小到这个(和类似的)代码片段,在那里我分配所有权使用共享指针的延迟任务的东西:
void DBStorage::dispose(std::shared_ptr<DataChunk>& dc)
{
backgroundQueue.queueTask([=]() {
assert( dc.use_count() == 1 );
if (dc->isDirty()) {
//store to disk
}
});
}
Run Code Online (Sandbox Code Playgroud)
(注意,运行lambda时共享指针的使用计数始终为1)
在执行之后,这个任务是null-ified pendingJob = nullptr;
,我希望它可以调用所有按值捕获的对象的析构函数,从而调用析DataChunk
构函数.但是,看起来在XCode/LLVM下 lc
的析构函数永远不会被调用; 明确地调用它的dtor,使用mutable
和删除std::function
简单的delete
也不起作用.
这是标准行为吗?我当然可以手动调用dc.reset()
它按预期工作,但这很有必要使用共享指针.
解决方案 显然,这是一个已知的gcc bug.
的Contrib
具有Xcode 5.0.2/clang 3.3输出的独立样品
#include <iostream>
#include <memory>
void fnRef(std::shared_ptr<int>& ptr)
{
auto lambda = [=]() { std::cout << ptr.use_count() << ':' << __PRETTY_FUNCTION__ << '\n'; };
lambda();
}
void fnVal(std::shared_ptr<int> ptr) …
Run Code Online (Sandbox Code Playgroud) 对于一个lambda,我想通过引用捕获一些东西,它已经通过引用保存在外部作用域中.假设引用的值超过lambda,但不是lamdba创建的范围.
我知道如果lambda 按值捕获引用变量,则会复制引用的对象.我想避免这个副本.
但是如果我通过引用捕获引用变量会发生什么?如果在执行lambda之前原始引用变量超出范围会怎么样?这样安全吗?换句话说:引用的引用后面的对象是lambda中引用的引用变量吗?
auto f() {
const auto & myRef = g();
return [&]{ myRef.doSomething(); };
}
f()(); // Safe?
Run Code Online (Sandbox Code Playgroud)