如何在C++中使用Lambda

起因

在阅读.Net Runtime源码的时候,发现C++有使用Lambda表达式,便学习了怎么使用的.C++的Lambda表达式和C#还是不太一样.C++中Lambda有3种方式.
  1. [] 没有捕获,和普通函数一样
  2. [=] 按值捕获
  3. [&] 按引用捕获

简单学习,如何在C++使用Lambda

#include <iostream>
#include <functional>

using namespace std;

int test(int num)
{
	return num + 100;
}

int sum_func(int a, function<int(int)> calc)  //使用function<>需要引入头文件functional
{
	return calc(a);
}

int main(int argc, char* argv[])
{
	auto func = [](int num) { cout << "num=" << num << endl; };  //创建一个没有返回值lambda表达式
	func(5);   //调用Lambda

	auto func2 = [](int num) { return num += 100; };             //创建一个返回int类型的lambda表达式

	int sum = func2(200);
	cout << "sum=" << sum << endl;

	int val1 = sum_func(100, [&](int num) { return num + 100; }); //将lambda表达式作为参数

	int val2 = sum_func(100, test);				      //把函数作为参数
	cout << "val1=" << val1 << endl;
	cout << "val2=" << val2 << endl;
	cin.get();

	return 0;
}

如何在C++使用Lambda表达式

.Net Runtime源码是这样使用Lambda的

inline string_t build_file_list(
    const string_t& dir,            //传入路径
    const char_t* ext,              //扩展名
    std::function<bool(const char_t*)> should_add) //接收一个函数或者lambda表达式
{
    assert(ext != nullptr);

    string_t dir_local = dir;
    dir_local.append(W("*"));
    dir_local.append(ext);

    WIN32_FIND_DATA data;
    HANDLE findHandle = ::FindFirstFileW(dir_local.data(), &data); //根据路径查找路径下第一个文件
    if (findHandle == INVALID_HANDLE_VALUE)
        return {};

    stringstream_t file_list;
    do
    {
        if (!(data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
        {
            // ToLower for case-insensitive comparisons
            char_t* fileNameChar = data.cFileName; //获取文件名
            while (*fileNameChar)
            {
                *fileNameChar = towlower(*fileNameChar);
                fileNameChar++;
            }

            if (should_add(data.cFileName))      //调用lambda或者函数
                file_list << dir << data.cFileName << env_path_delim;
        }
    } while (FALSE != ::FindNextFileW(findHandle, &data)); //继续下一个文件

    ::FindClose(findHandle); //关闭句柄,如果使用完毕不对句柄进行释放的话,就容易造成内存泄露

    return file_list.str();
}

int mian(int argc, char* argv[]) //源码中不是这样的.{

    std::set<string_t> name_set;
    pal::stringstream_t tpa_list;

    // Iterate over all extensions.
    for (const char_t* const* curr_ext = tpa_extensions; *curr_ext != nullptr; ++curr_ext)
    {
        const char_t* ext = *curr_ext;
        const size_t ext_len = pal::strlen(ext);

        // Iterate over all supplied directories.
        for (const string_t& dir : { core_libraries, core_root })
        {
            if (dir.empty())
                continue;

            assert(dir.back() == pal::dir_delim);
            //build_file_list 第一个参数为路径  第二个参数文件扩展名 第三个为lambda表达式,按引用捕获
            string_t tmp = pal::build_file_list(dir, ext, [&](const char_t* file)
                {
                    string_t file_local{ file };

                    // Strip the extension.
                    if (pal::string_ends_with(file_local, ext_len, ext))
                        file_local = file_local.substr(0, file_local.length() - ext_len);

                    // Return true if the file is new.
                    return name_set.insert(file_local).second;
                });

            // Add to the TPA.
            tpa_list << tmp;
        }
    }
}
秋风 2021-12-12