【问题标题】:How can I access local variables from inside a C++11 anonymous function?如何从 C++11 匿名函数内部访问局部变量?
【发布时间】:2011-10-29 09:02:22
【问题描述】:

我正在对向量(权重)进行简单的归一化,尝试使用 STL 算法使代码尽可能干净(我意识到这对于 for 循环来说非常简单):

float tot = std::accumulate(weights.begin(), weights.end(), 0.0);
std::transform(weights.begin(), weights.end(), [](float x)->float{return(x/tot);});

目前,匿名函数看不到 tot,因此无法编译。使局部变量对匿名函数可见的最佳方法是什么?

【问题讨论】:

  • 对不起,0 应该是 0.0!已编辑

标签: c++ lambda c++11 scope anonymous-function


【解决方案1】:

你需要一个闭包。

float tot = std::accumulate(weights.begin(), weights.end(), 0);
std::transform(weights.begin(), weights.end(), [tot](float x)->float{return(x/tot);});

在这种情况下,tot 是按值捕获的。 C++11 lambda 支持通过以下方式捕获:

  1. 值[x]
  2. 参考[&x]
  3. 通过引用[&]当前在范围内的任何变量
  4. 与 3 相同,但按值 [=]

您可以在逗号分隔的列表[x, &y] 中混合上述任何一种。

【讨论】:

  • 太棒了!是否有关于 STL 中 C++11 匿名函数使用的良好网络/书籍参考?我在网上找到的很多东西要么是匿名函数的过时解决方法,要么是随机的博客帖子。
  • @bd1 C++0x 上的维基百科其实相当不错。最后一个可供公众使用的标准草案也称为 n3424。不幸的是,目前还没有关于 C++0x 的书籍。
  • 如果您使用[=] 进行闭包并复制所有 封闭范围内的变量,这是否包括全局变量?它什么时候停止上升范围阶梯?
  • @Seth 我应该更明确一点:当使用默认捕获(& 或 =)时,只有在 lambda-body 中实际(odr-)使用的实体才会被捕获.这意味着只有在您访问全局时才会制作全局的副本。有关捕获默认值,请参阅 §5.1.2.11,有关范围规则,请参阅 §5.1.2.9。
【解决方案2】:

lambda 可以从环境范围“捕获”变量:

[ ..., N, ... ](int a, int b) -> int  { return (a + b) * N; }
 ^^^^^^^^^^^^^  ^^^^^^^^^^^^     ^^^^
 captured vars  local params     ret.type

您可以按值或按引用进行捕获,并且可以使用特殊语法[=] 和[&] 从环境范围捕获任何东西,即您实际最终使用的任何东西。

【讨论】:

  • 如果我将 lambda 解析为函数参数会怎样。它会抛出一个错误,指出 lambda 函数不是参数的正确类型。
  • @Acidic:由于你不能说出 lambda 表达式的 type,所以很难有参数是闭包类型的 function。通常,如果您需要管理可调用对象的异构集合,您将使用函数 templates 来推断类型,或者使用类型擦除包装器(例如 std::function)。
【解决方案3】:

您需要将tot添加到“捕获列表”中:

float tot = std::accumulate(weights.begin(), weights.end(), 0);
std::transform(weights.begin(), weights.end(), [tot](float x)->float{return(x/tot);});

或者,您可以使用默认捕获来隐式捕获tot:

float tot = std::accumulate(weights.begin(), weights.end(), 0);
std::transform(weights.begin(), weights.end(), [=](float x)->float{return(x/tot);});

【讨论】:

    猜你喜欢
    • 2016-05-28
    • 2013-08-16
    • 2012-12-31
    • 1970-01-01
    • 2020-08-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-26
    相关资源
    最近更新 更多