【static 与 lambda表达式 生命周期】

static 生命周期

作用域差异

int a = 0: 如果 a 是在函数内部声明的,那么 a 是一个局部变量,其作用域仅限于该函数内部。
static int a = 0: 如果 a 是在函数内部声明的,那么 a 仍然是一个局部变量,但其作用域被限制在声明它的源文件中,即它对其他源文件不可见。

生命周期变化

int a = 0: 局部变量的生命周期仅限于函数执行期间。每次函数调用时,a 都会被重新初始化为0,函数执行完毕后,a 就会被销毁。
static int a = 0: 静态局部变量的生命周期是整个程序的运行期间。第一次执行到 static int a = 0 时,a 会被初始化为0,之后即使函数执行完毕,a 的值也会被保留,下次函数调用时,a 会保持上次的值。

#include<stdio.h>
 
void example() { 
    int a = 0; // 局部变量 
    a++; 
    printf("a = %d\n", a); 
} 
 
void static_example() { 
    static int a = 0; // 静态局部变量 
    a++; 
    printf("static a = %d\n", a); 
} 
 
int main() { 
    example(); // 输出 a = 1 
    example(); // 输出 a = 1 
 
    static_example(); // 输出 static a = 1 
    static_example(); // 输出 static a = 2 
 
    return 0; 
} 

lambda表达式

int main(){
    int a = 0; //非静态 
    auto pfn = [=]() mutable{ //值捕获
        a++; //实际操作的只是a的一个副本 并非main函数中的a
    };
    pfn();
    std::cout << a << std::endl; // 0 结果不会改变
}

int main() {
    static int a = 0; // 静态局部变量 在函数的调用期间a的值会继续保持
    auto pfn = [=]() mutable { // 值捕获
        a++; 
    };
    pfn(); // 调用 lambda 函数
    std::cout << a << std::endl; // 1

    pfn(); // 调用 lambda 函数
    std::cout << a << std::endl; // 2
}

int main(){
    static int a = 0;
    // [a = a] 表示通过值捕获外部变量a的值并赋给了当前lamada内的a 
    //  Lambda 表达式内部的 a 是外部 a 的一个拷贝
    auto pfn = [a = a]() mutable{ 
        a++; //不会影响外部的a
    };
    pfn();
    std::cout << a << std::endl; // 0
}

//引用捕获会影响到lamada函数的外部
int main(){
    int a = 0;
    // [&] 捕获所有外部变量的引用 mutable关键字表示可以修改被捕获的变量的值
    auto pfn = [&]() mutable{ 
        a++;
    };
    pfn();
    std::cout << a << std::endl; // 1
}

int main(){
    static int a = 0;
    auto pfn = [&]() mutable{ 
        a++;
    };
    pfn();
    std::cout << a << std::endl; // 1
}

int main(){
    static int a = 0;
    // [&a = a] 表示通过引用捕获外部变量a并赋给了当前lamada内的a 
    //  Lambda 表达式内部的 a 是外部 a 的一个引用
    auto pfn = [&a = a]() mutable{ 
        a++; //影响外部的a
    };
    pfn();
    std::cout << a << std::endl; // 1
}
<think>嗯,用户现在想了解C++11中lambda表达式的用法和示例。我需要结合他们之前提供的引用信息,以及他们之前关于std::function的问题来组织回答。首先,用户之前已经接触过std::function,所以可能需要将lambdastd::function结合起来讲解,比如如何将lambda赋值给std::function。 接下来,用户提供的引用中有四个关于lambda的例子,我需要从中提取关键点。引用[1]提到了lambda的基本结构,包括捕获列表、参数列表、返回类型等。引用[2]和[3]给出了简单的lambda示例,比如加法操作。引用[4]则展示了lambda在STL算法中的应用,比如for_each统计偶数数量。 我应该从基本语法开始,逐步展开,确保每个部分都有示例代码。比如先讲基本结构,再讲捕获列表的不同方式,然后返回值类型,最后应用场景。同时,要注意用户可能关心lambdastd::function的结合使用,比如如何将lambda作为回调函数传递给std::function,这在之前的回答中已经提到过。 另外,用户可能需要知道lambda的类型是什么,是否可以重用,或者如何传递。引用中的例子显示使用auto来声明lambda变量,但用户可能想知道是否可以用其他方式,比如std::function。比如,可以提到lambda可以赋值给对应的std::function类型,这样可以在需要的时候存储和传递。 还要注意捕获列表的细节,比如值捕获、引用捕获的区别,以及mutable关键字的作用。引用中的示例[3]和[4]分别使用了值捕获和引用捕获,特别是引用[4]中的count变量通过引用捕获来修改外部变量。需要解释清楚这些用法,避免用户误解。 此外,用户可能会关心lambda的性能,比如普通函数或函数对象相比如何。可能需要在回答中提到lambda的性能通常函数对象类似,但捕获方式可能会影响性能,比如引用捕获可能带来悬垂引用的风险,而值捕获会增加拷贝开销。 最后,生成的相关问题需要围绕用户可能进一步探索的方向,比如lambda的实现原理、函数对象的比较、在模板中的应用,以及捕获列表的陷阱等。这些能帮助用户深入理解lambda表达式。</think>### C++11 Lambda表达式详解实战指南 #### 一、核心语法结构 Lambda表达式完整语法为: $$[capture-list] (params) mutable \quad exception \quad -> \quad return-type \quad \{ \quad body \quad \}$$ 基础简化版(90%场景适用): ```cpp auto lambda = [](int a, int b) { return a + b; }; // 自动推导返回值类型[^2] ``` #### 二、关键组成要素 1. **捕获列表**(Capture List) - `[]`:不捕获任何外部变量 - `[=]`:值捕获所有可见变量(副本) - `[&]`:引用捕获所有可见变量 - `[x]`:仅值捕获x - `[&y]`:仅引用捕获y - 混合捕获示例:`[=, &z]` 2. **参数列表** ```cpp auto print = [](const std::string& msg) { std::cout << msg << "\n"; }; print("Hello Lambda"); // 输出:Hello Lambda[^3] ``` 3. **mutable关键字** ```cpp int counter = 0; auto inc = [=]() mutable { ++counter; // 需mutable才能修改值捕获的副本 return counter; }; ``` 4. **返回值类型** ```cpp auto precise_div = [](double a, double b) -> double { if(b == 0) throw std::invalid_argument("除数不能为0"); return a / b; };[^1] ``` #### 三、典型应用场景 1. **STL算法增强** ```cpp std::vector<int> v{3,1,4,1,5,9,2,6}; std::sort(v.begin(), v.end(), [](int a, int b) { return a % 2 < b % 2; // 偶数在前奇数在后 });[^4] ``` 2. **异步编程** ```cpp std::thread t([&]{ std::cout << "线程ID:" << std::this_thread::get_id() << "\n"; }); t.join(); ``` 3. **GUI事件处理** ```cpp button.onClick([this]{ updateUI(); // 捕获this指针访问成员函数 }); ``` 4. **std::function结合** ```cpp std::function<int(int)> factorial = [&](int n) { return n <= 1 ? 1 : n * factorial(n-1); };[^3] ``` #### 四、高级技巧 1. **泛型LambdaC++14+)** ```cpp auto generic_add = [](auto a, auto b) { return a + b; }; std::cout << generic_add(3.14, 2.718); // 输出5.858 ``` 2. **初始化捕获(C++14+)** ```cpp auto p = std::make_unique<int>(42); auto lambda = [ptr = std::move(p)]{ return *ptr; // 安全转移所有权 }; ``` 3. **IIFE模式(立即调用函数表达式)** ```cpp const auto config = [&]{ JsonParser parser; parser.load("config.json"); return parser.getConfig(); }(); // 立即执行并返回结果 ``` #### 五、性能注意事项 1. **捕获优化**: - 优先使用显式捕获 `[var]` 代替 `[=]`/`[&]` - 大对象使用引用捕获时注意生命周期 2. **类型特征**: ```cpp static_assert(std::is_invocable_v<decltype(lambda), int, int>); ``` 3. **调试技巧**: - 使用 `decltype` 查看lambda类型特征 - 通过 `target_type()` 检测std::function包装的调用体类型 --相关问题--: 1. Lambda表达式如何实现闭包功能? 2. 值捕获引用捕获在内存管理上有何差异? 3. Lambda表达式仿函数(functor)有何性能差异? 4. 在模板编程中如何完美转发Lambda参数? 5. 如何捕获类成员变量时的正确语法?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值