前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >C++ 中文周刊 2024-04-06 第153期

C++ 中文周刊 2024-04-06 第153期

作者头像
王很水
发布2024-07-30 15:04:18
760
发布2024-07-30 15:04:18
举报
文章被收录于专栏:C++ 动态新闻推送

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

欢迎投稿,推荐或自荐文章/软件/资源等,评论区留言

本期文章由 HNY 赞助

最近博客内容较少,所以基本整合起来发

资讯

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

编译器信息最新动态推荐关注hellogcc公众号 本周更新 2024-03-20 第246期

最近的热门事件无疑是xz被植入后门了,埋木马的哥们主动参与社区贡献,骗取信任拿到直接commit权限

趁主要维护人休假期间埋木马,但是木马有问题回归测试被安全人员发现sshd CPU升高,找到xz是罪魁祸首

无间道搁这

文章

How can I tell C++ that I want to discard a nodiscard value? https://devblogs.microsoft.com/oldnewthing/20240329-00/?p=109592

std::ignore 或者 decltype(std::ignore) _; 然后用 _,或者不自己写,等c++26

Step-by-Step Analysis of Crash Caused by Resize from Zero https://light-city.medium.com/step-by-step-analysis-of-crash-caused-by-resize-from-zero-30ad1562b6cc

resize 的参数为负数会异常(比如参数溢出意外负数)

有句讲句,标准库里的异常有时候很奇怪,大动干戈,副作用还是异常应该有明显的区分。但是目前来看显然是一股脑全异常了

比如stoi异常,这些场景里expect<T>更合适,或者c传统的返回值处理更合理一些

RDMA性能优化经验浅谈(一) https://zhuanlan.zhihu.com/p/522332998

科普

GCC 14 Boasts Nice ASCII Art For Visualizing Buffer Overflows https://www.phoronix.com/news/GCC-14-fanalyzer-Enhancements

告警更明显一些

Improvements to static analysis in the GCC 14 compiler https://developers.redhat.com/articles/2024/04/03/improvements-static-analysis-gcc-14-compiler

gcc14加了个-fanalyzer

包括上面的buffer溢出分析,死循环分析,比如 https://godbolt.org/z/vn55nn43z

代码语言:javascript
复制
void test (int m, int n) {
  float arr[m][n];
  for (int i = 0; i < m; i++)
    for (int j = 0; j < n; i++)
      arr[i][j] = 0.f;
  /* etc */
}

这里里面的循环条件一直没变,所以一直是死的

编译器能分析出问题

代码语言:javascript
复制
<source>: In function 'test':
<source>:5:23: warning: infinite loop [CWE-835] [-Wanalyzer-infinite-loop]
    5 |     for (int j = 0; j < n; i++)
      |                     ~~^~~
  'test': events 1-5
    |
    |    5 |     for (int j = 0; j < n; i++)
    |      |                     ~~^~~  ~~~
    |      |                       |     |
    |      |                       |     (4) looping back...
    |      |                       (1) infinite loop here
    |      |                       (2) when 'j < n': always following 'true' branch...
    |      |                       (5) ...to here
    |    6 |       arr[i][j] = 0.f;
    |      |       ~~~~~~~~~        
    |      |             |
    |      |             (3) ...to here
    |
ASM generation compiler returned: 0
<source>: In function 'test':
<source>:5:23: warning: infinite loop [CWE-835] [-Wanalyzer-infinite-loop]
    5 |     for (int j = 0; j < n; i++)
      |                     ~~^~~
  'test': events 1-5
    |
    |    5 |     for (int j = 0; j < n; i++)
    |      |                     ~~^~~  ~~~
    |      |                       |     |
    |      |                       |     (4) looping back...
    |      |                       (1) infinite loop here
    |      |                       (2) when 'j < n': always following 'true' branch...
    |      |                       (5) ...to here
    |    6 |       arr[i][j] = 0.f;
    |      |       ~~~~~~~~~        
    |      |             |
    |      |             (3) ...to here
    |
Execution build compiler returned: 0
Program returned: 255

这个功能非常有用 gcc14已经发布,能体验到赶紧用起来,免费的静态检查了属于是

A case in API ergonomics for ordered containers https://bannalia.blogspot.com/2024/04/a-case-in-api-ergonomics-for-ordered.html

range的问题,如果range 的顺序颠倒,可能会产生未定义行为

举个例子,正常的范围使用

代码语言:javascript
复制

std::set<int> x=...;

// elements in [a,b]
auto first = x.lower_bound(a);
auto last  = x.upper_bound(b);
 
while(first != last) std::cout<< *first++ <<" ";

// elements in [a,b)
auto first = x.lower_bound(a);
auto last  = x.lower_bound(b);

// elements in (a,b]
auto first = x.upper_bound(a);
auto last  = x.upper_bound(b);

// elements in (a,b)
auto first = x.upper_bound(a);
auto last  = x.lower_bound(b);

这里的用法的潜在条件是a < b,如果不满足,就完蛋了, 似乎没有办法预防写错,手动assert?

这也容易引起错误,能不能让使用者不要用接口有隐形成本?

boost multiindex设计了一种接口

代码语言:javascript
复制
template<typename LowerBounder,typename UpperBounder>
std::pair<iterator,iterator>
range(LowerBounder lower, UpperBounder upper);

显然,不同的类型,隐含一层检查,看上去不好用,但是结合boost lambda2,非常直观

代码语言:javascript
复制
// equivalent to std::set<int>
boost::multi_index_container<int> x=...;

using namespace boost::lambda2;

// [a,b]
auto [first, last] = x.range(_1 >= a, _1 <= b);

// [a,b)
auto [first, last] = x.range(_1 >= a, _1 < b);

// (a,b]
auto [first, last] = x.range(_1 > a,  _1 <= b);

// (a,b)
auto [first, last] = x.range(_1 > a,  _1 < b);
代码语言:javascript
复制

倾向于返回range处理,而不是手动拿到range,即使出现a>b的场景,顶多返回空range

这样要比上面的用法更安全一些

唉,API设计的问题还是有很多需要关注的地方

C++ left arrow operator https://www.atnnn.com/p/operator-larrow/

幽默代码一例(别这么写)

代码语言:javascript
复制
#include <iostream>
 
template<class T>
struct larrow {
    larrow(T* a_) : a(a_) { }
    T* a;
};
 
template <class T, class R>
R operator<(R (T::* f)(), larrow<T> it) {
    return (it.a->*f)();
}
 
template<class T>
larrow<T> operator-(T& a) {
    return larrow<T>(&a);
}
 
struct C {
    void f() { std::cout << "foo\n"; }    
};
 
int main() {
    C x;
    (&C::f)<-x;
}
Upgrading the compiler: undefined behaviour uncovered https://www.sandordargo.com/blog/2024/04/03/upgrading-the-compiler-and-undefined-behaviour

TLDR enum没指定默认值的bug,类似int不指定默认值

Trivial, but not trivially default constructible https://quuxplusone.github.io/blog/2024/04/02/trivial-but-not-default-constructible/

一个例子

代码语言:javascript
复制
template<class T>
struct S {
    S() requires (sizeof(T) > 3) = default;
    S() requires (sizeof(T) < 5) = default;
};

static_assert(std::is_trivial_v<S<int>>);
static_assert(not std::is_default_constructible_v<S<int>>);

是trivial的,但是构造函数有点多,就没法默认构造

你问这有什么用,确实没用。当不知道好了

今天也和读者聊天问push back T构造异常了咋办,

那我只能说这个T的实现很没有素质,除了bad alloc别的老子不想管

希望大家都做一个有素质的人

Understanding and implementing fixed point numbers http://www.sunshine2k.de/articles/coding/fp/sunfp.html

看不懂

Random distributions are not one-size-fits-all (part 1) https://codingnest.com/random-distributions-are-not-one-size-fits-all-part-1/
Random distributions are not one-size-fits-all (part 2) https://codingnest.com/random-distributions-are-not-one-size-fits-all-part-2/

随机数生成和场景关联程度太大了,lemire的算法省掉了取余% 但是部分场景性能并不能打败使用取余%的版本

How fast is rolling Karp-Rabin hashing? https://lemire.me/blog/2024/02/04/how-fast-is-rolling-karp-rabin-hashing/

其实就是滚动hash,比如这种

代码语言:javascript
复制
uint32_t hash = 0;
for (size_t i = 0; i < len; i++) {
  hash = hash * B + data[i];
}
return hash;

这个B可能是个质数,比如31,不过不重要

考虑一个字符串子串匹配场景,这种场景下得计算字串hash,比如长字符串内长度为N的子串,代码类似这样

代码语言:javascript
复制
for(size_t i = 0; i < len-N; i++) {
  uint32_t hash = 0;
  for(size_t j = 0; j < N; j++) {
    hash = hash * B + data[i+j];
  }
  //...
}

这个代码的问题是效率低,有没有什么优化办法?

显然这里面有重复计算,到N之前的hash计算完全可以提前算出来

后面变动的减掉就行

代码语言:javascript
复制
uint32_t BtoN = 1;
for(size_t i = 0; i < N; i++) { BtoN *= B; }

uint32_t hash = 0;
for(size_t i = 0; i < N; i++) {
  hash = hash * B + data[i];
}
// ...
for(size_t i = N; i < len; i++) {
  hash = hash * B + data[i] - BtoN * data[i-N];
  // ...
}

不知道你看懂没?

这样提前算好性能翻个五倍没啥问题

代码在这里 https://github.com/lemire/clhash/

还有这个 https://github.com/lemire/rollinghashcpp

视频

C++ Weekly - Ep 421 - You're Using optional, variant, pair, tuple, any, and expected Wrong! https://www.youtube.com/watch?v=0yJk5yfdih0&ab_channel=C%2B%2BWeeklyWithJasonTurner

不要返回类似optional这种盒子类型,会破坏RVO

StatusOr<T> 应该也不太合适

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-04-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 CPP每周推送 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 资讯
  • 文章
    • How can I tell C++ that I want to discard a nodiscard value? https://devblogs.microsoft.com/oldnewthing/20240329-00/?p=109592
      • Step-by-Step Analysis of Crash Caused by Resize from Zero https://light-city.medium.com/step-by-step-analysis-of-crash-caused-by-resize-from-zero-30ad1562b6cc
        • RDMA性能优化经验浅谈(一) https://zhuanlan.zhihu.com/p/522332998
          • GCC 14 Boasts Nice ASCII Art For Visualizing Buffer Overflows https://www.phoronix.com/news/GCC-14-fanalyzer-Enhancements
            • Improvements to static analysis in the GCC 14 compiler https://developers.redhat.com/articles/2024/04/03/improvements-static-analysis-gcc-14-compiler
              • A case in API ergonomics for ordered containers https://bannalia.blogspot.com/2024/04/a-case-in-api-ergonomics-for-ordered.html
                • C++ left arrow operator https://www.atnnn.com/p/operator-larrow/
                  • Upgrading the compiler: undefined behaviour uncovered https://www.sandordargo.com/blog/2024/04/03/upgrading-the-compiler-and-undefined-behaviour
                    • Trivial, but not trivially default constructible https://quuxplusone.github.io/blog/2024/04/02/trivial-but-not-default-constructible/
                      • Understanding and implementing fixed point numbers http://www.sunshine2k.de/articles/coding/fp/sunfp.html
                        • Random distributions are not one-size-fits-all (part 1) https://codingnest.com/random-distributions-are-not-one-size-fits-all-part-1/
                          • Random distributions are not one-size-fits-all (part 2) https://codingnest.com/random-distributions-are-not-one-size-fits-all-part-2/
                            • How fast is rolling Karp-Rabin hashing? https://lemire.me/blog/2024/02/04/how-fast-is-rolling-karp-rabin-hashing/
                            • 视频
                              • C++ Weekly - Ep 421 - You're Using optional, variant, pair, tuple, any, and expected Wrong! https://www.youtube.com/watch?v=0yJk5yfdih0&ab_channel=C%2B%2BWeeklyWithJasonTurner
                              领券
                              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档