C++ 中文周刊 第136期

2024-07-30 14:40:05 浏览数 (2)

周刊项目地址[1]

RSS https://github.com/wanghenshui/cppweeklynews/releases.atom

欢迎投稿,推荐或自荐文章/软件/资源等

请提交 issue[3]

感谢 不语 赞助

最近在找工作准备面试题,更新可能有些拖沓,见谅

以后可能要改变一下内容

一周发文章总结,一周发视频总结,这样两种内容交叉一下

本期发视频总结

资讯

标准委员会动态/ide/编译器信息放在这里

编译器信息最新动态推荐关注hellogcc公众号 OSDT Weekly 2023-10-25 第225期

视频

CPPNorth去年的讲一下。今年的PPT没全放出来

Amir Kirsh - Are your Structures Bindable

怎么检测一个类型是否能结构化展开?structure_bindale?

这也是一个SO上的提问 https://stackoverflow.com/questions/63369361/how-to-define-a-concept-of-a-object-that-is-can-be-structured-binding

代码在 https://godbolt.org/z/ocox9sqed

不知道什么场景能用上。看一乐

Amir Kirsh - The fine details behind C containers and algorithms

一些容器使用上的经验/坑

vector push_back的T有三种场景

  • • trivially copyable 直接memcopy
  • • nothrow_move_constructible 直接move 这就要求T的move构造要noexcept
  • • 拷贝构造

std::copy 可能mommove 可能for循环无优化,注意使用

list原地sort通常不如拷贝到vector再sort 数据局部性问题

开头插入,list还是vector都不如 reserve预留空间 push_back 反转 reverse 快

尽可能降低挪动

https://quick-bench.com/q/Cx35L5th0bsvDMVHCdK61g08_z4 这个思路还是挺有意思的

按照index下标erase vector的优化,可以通过move来代替erase,最后只erase一次

这里index是降序的

代码语言:javascript复制
size_t removed = 0;
for(auto index: indices_to_erase) { // indices_to_erase are sorted in descending order
  std::move(vec.begin()   index   1, vec.end() - removed, vec.begin()   index);
    removed;
}
vec.erase(vec.end() - removed, vec.end());

降低交换次数,move相当于交换 移动,减少拷贝,删除的越多,收益越大

如果index数组是升序的,怎么写?

unordered_map的优化

尽可能用insert_or_assign,比赋值快

https://stackoverflow.com/questions/63041408/unordered-map-excess-calls-to-hash-function

计算hash过于频繁

我觉得还是别用这破玩意了

try_emplace提高性能,这个之前咱们也提过,但一定要用对,不然可能性能下降。或者装作不知道这个函数吧

另外删改写回场景c 17可以通过extract node insert node实现,性能更好一些

https://quick-bench.com/q/QtFK3ZJSXuf53l82e_z96Mq8fyk

range尽可能使用

代码语言:javascript复制
constexpr std::string_view words{"Hello-_-C  -_-20-_-!"};
constexpr std::string_view delim{"-_-"};
for (const auto word : std::views::split(words, delim)) {
  std::cout << std::quoted(std::string_view(word.begin(), word.end())) << ' ';
}

或者用 https://zh.cppreference.com/w/cpp/ranges/lazy_split_view

为啥还有lazy版本?难道split_view不是lazy的?

并不是,主要原因是split_view比较难用 https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2210r2.html

不展开了跑题了朋友们

Dean Moldovan - A std-fs-path from bug to patch

std::fs::path 不是unicode-safe的

特殊字母会有问题,想要用utf-8,可以用std::fs::u8path

他们不会搞定制clang-tidy规则,改系统源代码,给std::fs::path加deprecate信息。。。

Timur Doumler - C Lambda Idioms

lambda转函数指针

代码语言:javascript复制
int main() {
  auto f =  [](int i){ return i * i; };
  static_assert(std::is_same_v<decltype(f), int(*)(int)>);
}
代码语言:javascript复制
注意这个加号

怎么立即执行lambda?加括号?有没有更好的写法?invoke

捕获初始化优化代码

比如这种

代码语言:javascript复制
const std::vector<std::string> vs = {"apple", "orange", "foobar", "lemon"};
const std::string prefix = "foo";
auto result = std::find_if(
    vs.begin(), vs.end(),
    [&prefix](const std::string& s) {
        return s == prefix   "bar";
    });
if (result != vs.end())
    std::cout << prefix << "-something found!n";

这个prefix的构造就很脑瘫,怎么写更合理?把"bar"放外面?如果"bar"没法放外面只能这么构造怎么办?

代码语言:javascript复制
const std::vector<std::string> vs = {"apple", "orange", "foobar", "lemon"};
const std::string prefix = "foo";
auto result = std::find_if(
    vs.begin(), vs.end(),
    [str = prefix   "bar" ](const std::string& s) {
        return s == str;
    });
if (result != vs.end())
    std::cout << prefix << "-something found!n";

通过捕获的构造来替换内部的构造

lambda递归调用

常规

代码语言:javascript复制
int main() {
  std::function<int(int)> f = [&](int i) {
    if (i == 0) return 1;
    return i * f(i - 1);
  };
  std::cout << f(5); // prints 120
}

function有类型擦除开销,有没有其他方案?Y组合子?这玩意是不是叫柯里化来着?

代码语言:javascript复制
int main() {
  auto f = [&](auto&& self, int i) {
    if (i == 0) return 1;
    return i * self(self, i - 1);
  };
  auto recursive = [](auto&& f, auto&&... args) {
    return f(f, std::forward<decltype(args)>(args)...);
  };
  std::cout << recursive(f, 5); // prints 120
}

c 23的deducing this可以很好的写出来

代码语言:javascript复制
int main() {
  auto f = [&](this auto&& self, int i){
    if (i == 0) return 1;
    return i * self(i - 1);
  };
  std::cout << f(5); // prints 120
}

这玩意结合overload惯用法可以有更花的玩法

代码语言:javascript复制
struct Leaf {};
struct Node;
using Tree = std::variant<Leaf, Node*>;
struct Node {
  Tree left, right;
};

template <typename... Ts>
struct overload : Ts... { using Ts::operator()...; }

int countLeaves(const Tree& tree) {
  return std::visit(overload{
      [] (const Leaf&) { return 1; },
      [] (this const auto& self, const Node* node) -> int {
        return visit(self, node->left)   visit(self, node->right);
      }
    }, 
    tree);
}

其他

P99 CONF 2023 | Adventures in Thread-per-Core Async with Redpanda and Seastar by Travis Downs

https://www.bilibili.com/video/BV1gg4y1d7jB/

redpanda有一些coroutine实践,有点意思

seastar是thread per core 消息传递 share nothing,异步的处理阻塞非常重要

原来的seaster是传递future continuation的,引入couroutine就可以把then链切成co_await

但引入coroutine也是有代价的

  • • 只要suspend就有栈开销,除非
    • • suspend不发生,不可达 不co_await co_yeild

小的任务,不建议coroutine,能同步就同步,不能同步再then链,不能then链再coroutine

开源项目需要人手

  • • asteria[4] 一个脚本语言,可嵌入,长期找人,希望胖友们帮帮忙,也可以加群384042845和作者对线
  • • Unilang[5] deepin的一个通用编程语言,点子有点意思,也缺人,感兴趣的可以github讨论区或者deepin论坛看一看。这里也挂着长期推荐了
  • • gcc-mcf[6] 懂的都懂
  • • https://gitee.com/okstar-org/ok-edu-desktop 一个IM通信软件,做IM的可以关注,现在正在做全面整合阶段,开始组建商业团队阶段,年底开始融资,你参加了就快发财了,会的快来
引用链接

[1] 周刊项目地址: https://github.com/wanghenshui/cppweeklynews [2] 手机qq点击进入: https://qm.qq.com/q/6NGizNPyG4 [3] 提交 issue: https://github.com/wanghenshui/cppweeklynews/issues [4] asteria: https://github.com/lhmouse/asteria [5] Unilang: https://github.com/linuxdeepin/unilang [6] gcc-mcf: https://gcc-mcf.lhmouse.com/

0 人点赞