C ++ lambda函数访问写入违规

时间:2014-04-30 18:26:37

标签: c++ c++11 lambda

我正在学习如何使用C ++ lambda函数和<functional>的{​​{1}}类。我正在努力解决这个问题Code Golf(挑战是咖喱晚餐)

我有这个功能:

function

为了测试这个我在main()中有这个代码:

// This creates a function that runs y a number of 
// times equal to x's return value.
function<void()> Curry(function<int()> x, function<void()> y)
{
    return [&]() {
        for (int i = 0; i < x(); i++)
        {
            y();
        }
    };
}

这会在Functional.h中抛出auto x = [](){ return 8; }; auto y = [](){ cout << "test "; }; auto g = Curry(x, y);

然而,当我将lambda函数从Curry()内部复制粘贴到我的main中时,就像这样:

Access violation reading location 0xCCCCCCCC.

我按预期运行代码。为什么会这样?

1 个答案:

答案 0 :(得分:7)

你有一些问题。

下面:

  return [&]() {

您通过引用捕获。您捕获的任何变量都必须具有超出您自己的生命周期。这意味着在捕获的变量和使用生命周期结束后,运行lambda会变为未定义的行为。当你返回这个lambda并捕获本地状态时,这似乎很可能发生。 (注意我说的变量 - 由于标准中的一个怪癖,[&]捕获变量而不是变量引用的数据,所以即使按&捕获[&]函数参数也是不安全的。这可能会在未来的标准版本中发生变化......这些特定的规则集在lambda实现中有一些优化(将[&] lambdas减少为具有1个指针的状态(!)),但它也引入了C ++中唯一一个有效引用参考变量的情况......)

将其更改为

  return [=]() {

并按值进行捕获。

甚至:

  return [x,y]() {

明确列出您的捕获。

当使用不超过当前范围的lambda时,我使用[&]。否则,我会明确地捕获我要使用的东西,因为在这种情况下,生命周期很重要。

下一步:

    for (int i = 0; i < x(); i++)

每次循环迭代都会运行x一次。看起来很傻!

相反:

    auto max = x();
    for (auto i = max; i > 0; --i)

运行max次,如果x的返回值更改为unsigned int或其他任何内容,则会发生这种情况。

或者:

    int max = x();
    for (int i = 0; i < max; ++i)

两次运行x一次,如果x返回-1则行为更好。

或者,您可以使用模糊操作符-->

    int count = x();
    while( count --> 0 )

如果你想让你的代码不可读。 ;)