惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

S
Schneier on Security
有赞技术团队
有赞技术团队
T
The Blog of Author Tim Ferriss
F
Fortinet All Blogs
D
DataBreaches.Net
F
Full Disclosure
腾讯CDC
博客园 - 【当耐特】
MyScale Blog
MyScale Blog
Stack Overflow Blog
Stack Overflow Blog
小众软件
小众软件
Hugging Face - Blog
Hugging Face - Blog
Last Week in AI
Last Week in AI
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
爱范儿
爱范儿
The GitHub Blog
The GitHub Blog
Engineering at Meta
Engineering at Meta
大猫的无限游戏
大猫的无限游戏
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
S
SegmentFault 最新的问题
The Register - Security
The Register - Security
WordPress大学
WordPress大学
博客园 - 聂微东
雷峰网
雷峰网
J
Java Code Geeks
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
P
Privacy International News Feed
酷 壳 – CoolShell
酷 壳 – CoolShell
A
Arctic Wolf
Scott Helme
Scott Helme
C
Cyber Attacks, Cyber Crime and Cyber Security
T
Tor Project blog
博客园 - 三生石上(FineUI控件)
Know Your Adversary
Know Your Adversary
AWS News Blog
AWS News Blog
G
Google Developers Blog
www.infosecurity-magazine.com
www.infosecurity-magazine.com
C
CERT Recently Published Vulnerability Notes
O
OpenAI News
Project Zero
Project Zero
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Application and Cybersecurity Blog
Application and Cybersecurity Blog
云风的 BLOG
云风的 BLOG
N
News and Events Feed by Topic
MongoDB | Blog
MongoDB | Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Microsoft Security Blog
Microsoft Security Blog
Cisco Talos Blog
Cisco Talos Blog
P
Palo Alto Networks Blog
Schneier on Security
Schneier on Security

ImCBC

git-cm:在终端里用 LLM 生成 commit message Token Tracker - 追踪 Coding Agent 的 Token 使用情况 AI Coding 工具的实践经验 2025年终总结 行车记录仪视频拼接 生成文章摘要 DMA拼接 Base64压缩 2024年终总结 二维数据可视化工具-painter
C++闭包二
bing · 2024-09-11 · via ImCBC

“多年以前"写过一篇关于C++闭包的文章,现在看来基本是关于lambda的介绍。随着经验的增加,对闭包的理解更加深刻。在上一篇文章中,介绍了我编写的一个tiny_cmdline库,随后我对一些tiny库更感兴趣,便想着做了一个集合,取名为tinylib,其中有一个tiny库是关于match的。调用方式如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
  using namespace tiny_utility;
  auto match_op = match(
      "1" | [](const auto &i) { ASSERT_EQ(i, "1"); },                              // no line break
      "2" | [](const auto &i) { ASSERT_EQ(i, "2"); },                              // no line break
      "3" | [](const auto &i) { ASSERT_EQ(i, "3"); },                              // no line break
      std::set<std::string>{"5", "6"} | [](const auto &i) { ASSERT_NE(i, "4"); },  // no line break
      placeholder | [](const auto &i) { ASSERT_TRUE(false); }                      // no line break
  );
  // for (const auto &key : std::vector<std::string>{"1", "2", "3", "4" , "5", "6"}) {
  for (const auto &key : std::vector<std::string>{"1", "2", "3", "5", "6"}) {
    match_op(key);
  }

考虑到case key的各种类型兼容,目前的match类是运行时构建的,并且是一个模板类(key的类型是各种各样的)。

如果在实际使用中,比如有某个query接口,是不会考虑在query接口中频繁构建match类的,一般会在构造或者其他初始化接口中构造一次,然后在query接口中多次调用。

但是针对match构造一次的情况,如何保存呢?不可能考虑在类的成员变量中写一长串的类型,并且这样也不适合match的扩展。

用闭包可以解决这问题,闭包的一个特点是可以隐藏一些局部变量:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
// query.h

class Query {
    // ...
    std::function<void(const std::string &)> match_op_;
};

// query.cpp
#include "tiny_match.h"

Query::Query() {
    auto match_op = match(
        "1" | [](const auto &i) { ASSERT_EQ(i, "1"); },                              // no line break
        "2" | [](const auto &i) { ASSERT_EQ(i, "2"); },                              // no line break
        "3" | [](const auto &i) { ASSERT_EQ(i, "3"); },                              // no line break
        std::set<std::string>{"5", "6"} | [](const auto &i) { ASSERT_NE(i, "4"); },  // no line break
        placeholder | [](const auto &i) { ASSERT_TRUE(false); }                      // no line break
    );
    match_op_ = [match_op](const std::string &key) { match_op(key); };
}

这样,Query类通过保存一个闭包函数,避免在类中声明可变长参数的match类型。

并且,也能发现可以在query.h声明文件中,隐藏tiny_match.h的头文件,只需要在query.cpp中包含即可。

tiny_match.h的实现在: https://github.com/caibingcheng/tinylib/blob/master/tiny_utility/tiny_match.h


根据match这个案例, 再来理解闭包这个概念:

  1. 可以捕获上层函数的局部变量, 比如match_op_捕获了match_op
  2. 可以隐藏局部变量, 比如match_op, 外部通过某些接口访问match_op_时, 是无法感知match_op的存在的
  3. 通过2, 闭包可以隐藏实现细节
  4. 一个"神奇"的通道, 外部接口居然可以访问到内部的局部变量, 尽管是这个局部变量的复制体