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

ein*_*sci 5 c++ lambda c++11

我正在学习如何利用C沿++ lambda函数<functional>function类.我正在尝试解决这个Code Golf作为练习(挑战是咖喱晚餐)

我有这个功能:

// 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();
        }
    };
}
Run Code Online (Sandbox Code Playgroud)

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

auto x = [](){ return 8; };
auto y = [](){ cout << "test "; };
auto g = Curry(x, y);
Run Code Online (Sandbox Code Playgroud)

这将抛出Access violation reading location 0xCCCCCCCC.Functional.h.

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

auto x = [](){ return 8; };
auto y = [](){ cout << "test "; };
auto g = [&]() {
    for (int i = 0; i < x(); i++)
    {
        y();
    }
};
Run Code Online (Sandbox Code Playgroud)

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

Yak*_*ont 8

你有一些问题.

这里:

  return [&]() {
Run Code Online (Sandbox Code Playgroud)

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

将其更改为

  return [=]() {
Run Code Online (Sandbox Code Playgroud)

并按价值捕获.

甚至:

  return [x,y]() {
Run Code Online (Sandbox Code Playgroud)

明确列出您的捕获.

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

下一个:

    for (int i = 0; i < x(); i++)
Run Code Online (Sandbox Code Playgroud)

x为每个循环迭代运行一次.好像很傻!

代替:

    auto max = x();
    for (auto i = max; i > 0; --i)
Run Code Online (Sandbox Code Playgroud)

运行max时间,并且如果返回值x改为unsigned int或者其他什么,它会发生.

要么:

    int max = x();
    for (int i = 0; i < max; ++i)
Run Code Online (Sandbox Code Playgroud)

它们都运行x一次,如果x返回则表现更好-1.

或者,您可以使用模糊运算符-->:

    int count = x();
    while( count --> 0 )
Run Code Online (Sandbox Code Playgroud)

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