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

推荐订阅源

MyScale Blog
MyScale Blog
F
Full Disclosure
Microsoft Azure Blog
Microsoft Azure Blog
Jina AI
Jina AI
Recent Announcements
Recent Announcements
美团技术团队
L
LangChain Blog
P
Privacy & Cybersecurity Law Blog
M
MIT News - Artificial intelligence
www.infosecurity-magazine.com
www.infosecurity-magazine.com
W
WeLiveSecurity
Engineering at Meta
Engineering at Meta
S
Security @ Cisco Blogs
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Help Net Security
Help Net Security
L
LINUX DO - 最新话题
S
Secure Thoughts
O
OpenAI News
Hacker News - Newest:
Hacker News - Newest: "LLM"
A
About on SuperTechFans
NISL@THU
NISL@THU
C
Cyber Attacks, Cyber Crime and Cyber Security
Cyberwarzone
Cyberwarzone
T
Tailwind CSS Blog
T
The Blog of Author Tim Ferriss
Recent Commits to openclaw:main
Recent Commits to openclaw:main
F
Fortinet All Blogs
B
Blog
IT之家
IT之家
T
Tor Project blog
L
Lohrmann on Cybersecurity
Webroot Blog
Webroot Blog
博客园 - 叶小钗
Simon Willison's Weblog
Simon Willison's Weblog
Application and Cybersecurity Blog
Application and Cybersecurity Blog
量子位
Security Latest
Security Latest
TaoSecurity Blog
TaoSecurity Blog
S
Schneier on Security
C
Cisco Blogs
博客园 - 三生石上(FineUI控件)
J
Java Code Geeks
Last Week in AI
Last Week in AI
The Last Watchdog
The Last Watchdog
博客园 - 聂微东
Cisco Talos Blog
Cisco Talos Blog
Security Archives - TechRepublic
Security Archives - TechRepublic
Google DeepMind News
Google DeepMind News
SecWiki News
SecWiki News

Bing's Blog

git-cm:在终端里用 LLM 生成 commit message Token Tracker - 追踪 Coding Agent 的 Token 使用情况 AI Coding 工具的实践经验 2025年终总结 行车记录仪视频拼接 生成文章摘要 DMA拼接 Base64压缩 2024年终总结 二维数据可视化工具-painter 对ToB和ToC的感受 轻量级参数解析库-tiny_cmdline C++标签派发技术
C++闭包二
bing · 2024-09-11 · via Bing's Blog

“多年以前"写过一篇关于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. 一个"神奇"的通道, 外部接口居然可以访问到内部的局部变量, 尽管是这个局部变量的复制体