C++ 中文周刊 2024-08-18 第166期

周刊项目地址

公众号

点击「查看原文」跳转到 GitHub 上对应文件,链接就可以点击了

qq群 点击进入

RSS

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

本期文章由 HNY 赞助

资讯

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

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

文章

彻底理解 C++ ABI

今天群聊提到了一个场景,unique_ptr传值加move 并不能完美优化掉,看代码


void consume(int* ptr);

void foo(int* ptr) {
    consume(ptr);
}

/*
foo:
        jmp     consume@PLT
*/
void consume(unique_ptr<int> ptr);

void foo(unique_ptr<int> ptr) {
    consume(std::move(ptr));  //
}

/*
foo(std::unique_ptr<int, std::default_delete<int> >):
        push    rbx
        sub     rsp, 16
        mov     rax, QWORD PTR [rdi]
        mov     QWORD PTR [rdi], 0
        lea     rdi, [rsp+8]
        mov     QWORD PTR [rsp+8], rax
        call    consume(std::unique_ptr<int, std::default_delete<int> >)
        mov     rdi, QWORD PTR [rsp+8]
        test    rdi, rdi
        je      .L1
        mov     esi, 4
        call    operator delete(void*, unsigned long)
.L1:
        add     rsp, 16
        pop     rbx
        ret
        mov     rbx, rax
        jmp     .L3
foo(std::unique_ptr<int, std::default_delete<int> >) [clone .cold]:
*/

主要原因是 函数实参在 caller 方析构, unique_ptr没有彻底优化掉。感觉可以优化掉

改成传引用,传&&甚至改成not_null都能省掉

void consume(not_null<int*> ptr); //std::unique_ptr<int> && 也可以

void foo(not_null<int*> ptr) {
    consume(ptr);  //
}
/*
foo(not_null<int*>):
        jmp     consume(not_null<int*>)
*/

感谢anms nugine ni fvs zwuis 讨论

godbolt https://godbolt.org/z/fbqEa4M1r

noexcept Can (Sometimes) Help (or Hurt) Performance

使用noexcept需要保证没有异常,否则生成的代码代价更高

通常来说noexcept是给move用的

另外有一个搞笑的场景

noexcept affects libstdc++’s unordered_set

libstdc++的 unordered set 对于noexcept限定 针对hash函数有特化

如果hash函数是noexcept 认为函数计算很轻,不额外保存key hash,否则会缓存key hash加速

这就导致一个尴尬的场景,对于int,这种优化是对的,对于string hash接口使用noexcept会弄巧成拙速度更慢

标准库对于noexcept限定应该给用户端保留余地,不要影响效果,如果影响,最好给出api约定,比如transparent compare

这种莫名其妙的限制很坑,可能喜欢秀一下用noexcept正好掉坑里

libstdc++ 说明 在这里

Temporarily dropping a lock: The anti-lock pattern

异步lock暂时解锁的组件。代码

template<typename Mutex>
struct anti_lock
{
    anti_lock() = default;

    explicit anti_lock(Mutex& mutex)
    : m_mutex(std::addressof(mutex)) {
        if (m_mutex) m_mutex->unlock();
    }

private:
    struct anti_lock_deleter {
        void operator()(Mutex* mutex) { mutex->lock(); }
    };

    std::unique_ptr<Mutex, anti_lock_deleter> m_mutex;
};

winrt::fire_and_forget DoSomething()
{
    auto guard = std::lock_guard(m_mutex);

    step1();

    // All co_awaits must be under an anti-lock.
    int cost = [&] {
        auto anti_guard = anti_lock(m_mutex);
        return co_await GetCostAsync();
    }();

    step2(cost);
}

Surprisingly Slow NaNs

https://voithos.io/articles/surprisingly-slow-nans/

代码存在0除0导致NAN NAN导致性能下降

规避?isnan判定 DCHECK

### What’s so hard about class types as non-type template parameters?

NTTP 支持类实例的困难原因 无法判定相等

有operator template()提案和反射提案的加持下可能有解

Reflection-based JSON in C++ at Gigabytes per Second

反射给普通库带来压倒性序列化速度,十倍以上!使用的是P2996实现

反射快来吧

互动环节

上周熬夜看了街霸6比赛 直接给我看的不困了,尤其是肯打aki那场,看的我心率110,真刺激

不过熬夜的后果就是一周都缓不过来。睡眠问题非常大,累计起来了,石油杯这个比赛作息太抽象了

时间真快啊,转眼夏天就过去了我靠,感觉啥也没干

东西太多根本看不过来,时间真是不够用

上一期

看到这里或许你有建议或者疑问或者指出错误,请留言评论! 多谢! 你的评论非常重要!也可以帮忙点赞收藏转发!多谢支持! 觉得写的不错那就给点吧, 在线乞讨 微信转账