C++ Lambda表达式不能捕获当前作用域的枚举,可以捕获另一个Labmda表达式,前者不必为后者传递捕获后者的捕获列表

本文探讨了C++ Lambda表达式不能捕获枚举和静态变量的原理,以及如何通过引用间接引用静态变量。通过实例展示了如何在Lambda中巧妙地处理这些限制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

C++ Lambda表达式不能捕获当前作用域的枚举,枚举在C++中也算是个类型,它不是变量,只有变量才可以被捕获,可以捕获另一个Labmda表达式,前者不必为后者传递捕获后者的捕获列表

另外,C++ Lambda表达式不能引用捕获当前方法|函数中的静态变量(是出于什么原因?),但定义一个非静态的引用变量引用那个静态变量,然后把这个引用传引用给Lambda表达式就可以“间接”引用静态变量了,绕过Lambda表达式不能捕获静态变量的障碍,

#include <iostream>
int main(int argc, char *argv[]){
    enum myenum{
        heihei=1,
        haha,
        halo
    };
    int a(3),b(1);
    static int c(5);
    auto Lambda1=[a,b]()->int{return a+b;};
    auto Lambda2=[a,b]()->int{return a-b;};
    auto Lambda3=[Lambda1,Lambda2,&c]()->int{return Lambda1()+Lambda2()+c;};
    std::cout<<Lambda3()<<"\n";
    std::cin>>a;
    return 0;
}
> Executing task: /usr/bin/clang++ -std=c++17 -stdlib=libc++ -g /Users/haypin/VScode/cpptest/Lambda.cpp -o /Users/haypin/VScode/cpptest/Lambda <

/Users/haypin/VScode/cpptest/Lambda.cpp:12:36: error: 'c' cannot be captured because it does not have automatic storage
      duration
    auto Lambda3=[Lambda1,Lambda2,&c]()->int{return Lambda1()+Lambda2()+c;};
                                   ^
/Users/haypin/VScode/cpptest/Lambda.cpp:9:16: note: 'c' declared here
    static int c(5);
               ^
1 error generated.
The terminal process "/bin/bash '-c', '/usr/bin/clang++ -std=c++17 -stdlib=libc++ -g /Users/haypin/VScode/cpptest/Lambda.cpp -o /Users/haypin/VScode/cpptest/Lambda'" terminated with exit code: 1.

Terminal will be reused by tasks, press any key to close it.


error: 'c' cannot be captured because it does not have automatic storage

定义一个引用d引用静态变量c,然后传引用给Lambda表达式就可以了,使Lambda表达式“间接引用“了静态变量:

#include <iostream>
int main(int argc, char *argv[]){
    enum myenum{
        heihei=1,
        haha,
        halo
    };
    int a(3),b(1);
    static int c(14);
    int &d=c;
    auto Lambda1=[a,b]()->int{return a+b;};
    auto Lambda2=[a,b]()->int{return a-b;};
    auto Lambda3=[Lambda1,Lambda2,/*&c*/&d]()->int{return Lambda1()+Lambda2()+d;};
    int nRes=Lambda3();
    std::cout<<nRes<<"\n";
    std::cin>>a;
    return 0;
}

 

.vscode/tasks.json:

{
	"version": "2.0.0",
	"tasks": [
		{
			"type": "shell",
			"label": "C/C++: clang++ build active file",
			"command": "/usr/bin/clang++",
			"args": [
				"-std=c++17",
				"-stdlib=libc++",
				"-g",
				"${file}",
				"-o",
				"${fileDirname}/${fileBasenameNoExtension}"
			],
			"options": {
				"cwd": "${workspaceFolder}"
			},
			"problemMatcher": [
				"$gcc"
			],
			"group": "build"
		}
	]
}

.vscode/launch.json:

{
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "type": "lldb",
            "request": "launch",
            "name": "Debug",
            "program": "${fileDirname}/${fileBasenameNoExtension}",
            "args": [],
            "cwd": "${workspaceFolder}",
            "console":"integratedTerminal",
            "preLaunchTask": "C/C++: clang++ build active file",
        }
    ]
}

mac10.15.6上VScode的clang++编译器默认支持的C++版本应该是低于C++11的,编译任务配置tasks.json中如果不给"-std=c++17"和"-stdlib=libc++"参数在编译时会指出auto类型说明符是C++11扩展,并且捕获列表还没编译成功:

参见VSCode官网文档:https://code.visualstudio.com/docs/cpp/config-clang-mac

补充:C++的Lambda表达式的引用列表捕获的变量或常量,是Lambda表达式定义处上溯作用域链名字查找的,在Lambda表达式执行时进行实参->形参传值或直接使用引用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值