自学内容网 自学内容网

C++ 封闭函数局部变量不能在 lambda 体中引用,除非其位于捕获列表中

在 C++ 中,lambda 表达式可以捕获外部作用域的变量,但为了能够在 lambda 体中使用这些变量,它们必须显式地列在 捕获列表 中。否则,这些变量就不能直接在 lambda 表达式内部使用。

为什么捕获列表很重要?

C++ 中的 lambda 表达式有一个非常重要的特性,就是它们 可以访问外部作用域的变量。但是为了保证 作用域的明确性和避免潜在的错误,C++ 要求在 lambda 的捕获列表中显式声明要捕获哪些外部变量。捕获列表就是位于 lambda 表达式的开始部分,用于捕获外部作用域中的变量。

示例 1:没有捕获的情况(编译错误)
cpp

#include <iostream>

void example() {
    int x = 5;
    
    // lambda 表达式没有捕获 x,所以不能在 lambda 体中使用 x
    auto lambda = []() {
        // 这里会导致编译错误,因为 x 没有被捕获
        std::cout << x << std::endl;
    };
    
    lambda();
}

int main() {
    example();
    return 0;
}

错误信息:

error: 'x' was not declared in this scope

示例 2:正确的捕获变量(编译通过)

要在 lambda 中引用外部变量,必须在捕获列表中声明这些变量,或者使用捕获所有变量的方式:

  • 2.1 捕获单个变量
    cpp
#include <iostream>

void example() {
    int x = 5;
    
    // lambda 捕获外部变量 x
    auto lambda = [x]() {
        std::cout << x << std::endl;  // 这里可以正确访问 x
    };
    
    lambda();
}

int main() {
    example();
    return 0;
}

输出:

5
  • 2.2 捕获多个变量
    cpp
#include <iostream>

void example() {
    int x = 5;
    int y = 10;
    
    // lambda 捕获多个外部变量
    auto lambda = [x, y]() {
        std::cout << "x: " << x << ", y: " << y << std::endl;
    };
    
    lambda();
}

int main() {
    example();
    return 0;
}

输出:

x: 5, y: 10
  • 2.3 捕获所有外部变量([=])
    如果你想捕获外部作用域中的所有变量,你可以使用 [=] 语法:

cpp

#include <iostream>

void example() {
    int x = 5;
    int y = 10;
    
    // 使用 [=] 捕获所有外部变量
    auto lambda = [=]() {
        std::cout << "x: " << x << ", y: " << y << std::endl;
    };
    
    lambda();
}

int main() {
    example();
    return 0;
}

输出:

x: 5, y: 10

  • 2.4 捕获所有外部变量并允许修改([&])
    如果你希望 lambda 可以修改外部作用域中的变量,你可以使用 [&] 来捕获所有变量,并通过引用来传递它们:

cpp

#include <iostream>

void example() {
    int x = 5;
    
    // 使用 [&] 捕获所有外部变量并按引用传递
    auto lambda = [&]() {
        x = 10;  // 修改 x 的值
        std::cout << "x: " << x << std::endl;
    };
    
    lambda();
    std::cout << "x after lambda: " << x << std::endl;
}

int main() {
    example();
    return 0;
}

输出:

x: 10
x after lambda: 10

总结

  • lambda 表达式 不允许直接使用外部作用域中的变量,除非它们被显式地捕获。
  • 捕获列表 [x] 可以捕获一个或多个外部变量,[=] 可以捕获所有外部变量(按值),而 [&] 捕获所有外部变量(按引用)。
  • 如果没有捕获列表,lambda 内部不能直接访问外部变量,这也是 C++ 对作用域和变量生命周期的保证。

通过捕获列表,C++ 保证了 lambda 的作用域不会无意中影响外部变量的生命周期,从而避免了潜在的错误和副作用。


原文地址:https://blog.csdn.net/u013798595/article/details/144208797

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!