公众号
qq群 手机qq点击进入
RSS https://github.com/wanghenshui/cppweeklynews/releases.atom
欢迎投稿,推荐或自荐文章/软件/资源等
感谢 不语 赞助
最近在找工作准备面试题,更新可能有些拖沓,见谅
以后可能要改变一下内容
一周发文章总结,一周发视频总结,这样两种内容交叉一下
本期发视频总结
标准委员会动态/ide/编译器信息放在这里
编译器信息最新动态推荐关注hellogcc公众号 OSDT Weekly 2023-10-25 第225期
CPPNorth去年的讲一下。今年的PPT没全放出来
怎么检测一个类型是否能结构化展开?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
不知道什么场景能用上。看一乐
一些容器使用上的经验/坑
vector push_back的T有三种场景
std::copy 可能memmove 可能for循环无优化,也有alias问题,不重叠会优化成memcpy 感谢吴乎指出.注意使用
list原地sort通常不如拷贝到vector再sort 数据局部性问题
开头插入,list还是vector都不如 reserve预留空间 + push_back + 反转 reverse 快
尽可能降低挪动
https://quick-bench.com/q/Cx35L5th0bsvDMVHCdK61g08_z4 这个思路还是挺有意思的
群友anien指出,测试数据/结论不可靠,明显受cache
我加上pad做了测试,发现确实 list还是快一些的https://quick-bench.com/q/JDIZFmwrlmqJwqCENhWLFEOhhC0
还是要考虑数据集的。感谢anien指正
按照index下标erase vector的优化,可以通过move来代替erase,最后只erase一次
这里index是降序的
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尽可能使用
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
不展开了跑题了朋友们
std::fs::path 不是unicode-safe的
特殊字母会有问题,想要用utf-8,可以用std::fs::u8path
他们不会搞定制clang-tidy规则,改系统源代码,给std::fs::path加deprecate信息。。。
lambda转函数指针
int main() {
auto f = +[](int i){ return i * i; };
static_assert(std::is_same_v<decltype(f), int(*)(int)>);
}
怎么立即执行lambda?加括号?有没有更好的写法?invoke
捕获初始化优化代码
比如这种
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”没法放外面只能这么构造怎么办?
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递归调用
常规
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组合子?
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可以很好的写出来
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惯用法可以有更花的玩法
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);
}
https://www.bilibili.com/video/BV1gg4y1d7jB/
redpanda有一些coroutine实践,有点意思
seastar是thread per core 消息传递 share nothing,异步的处理阻塞非常重要
原来的seaster是传递future continuation的,引入couroutine就可以把then链切成co_await
但引入coroutine也是有代价的
小的任务,不建议coroutine,能同步就同步,不能同步再then链,不能then链再coroutine
这个也是经验之谈,目前没有代码复现一下。群友anien指出llvm可能优化掉