Skip to content

C++ 中文周刊 2024-11-03 第171期

Compare
Choose a tag to compare
@wanghenshui wanghenshui released this 23 Nov 14:49
ad11b49

周刊项目地址

公众号

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

qq群 点击进入 满了加这俩 729240657 866408334

RSS

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

本期文章由 HNY 赞助 在此表示感谢

本期内容较少,掺杂一些互动


资讯

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

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

文章

How useful is the hint passed to the std::unordered_… collections?

emplace_hit 在有序map有很大作用,但是在无序容器,由于不允许重复,hint基本没啥用

但无序容器存在允许重复值的 multixx,这种场景可以用,一般来说用不着

总结了一个表格

实现 unordered_multixx unordered_xx
是否允许重复
msvc/STL 如果匹配就是用 如果匹配就使用
clang/libcxx 忽略 如果匹配就使用
gcc/libstdc++ (large or fast) 忽略 如果匹配就使用
gcc/libstdc++ (small and slow) 忽略 使用

libstdc++针对不同key的hash有快慢识别,默认是快的 (long double慢) 这里有坑不知道大家记得不

群友mapleFU投稿

之前用 hint 优化过一些有序容器相关的处理( io range 维护什么的),感觉还是挺有用的

工厂函数的几种实现

其实就是static map,可以有多种维护方法

  • 可以利用类来封装,利用宏生成多个static变量构造,来注册到map
  • singleton模版注册也可以,利用模版实例化来调用注册到map 这两种都适合分散写法

这里有个例子 https://www.cnblogs.com/qicosmos/p/5090159.html

我就不贴代码了,脑补一下就有了

  • 直接注册也可以,比如
static std::unordered_map<std::string, OptionTypeInfo>
    lru_cache_options_type_info = {
        {"capacity",
         {offsetof(struct LRUCacheOptions, capacity), OptionType::kSizeT,
          OptionVerificationType::kNormal, OptionTypeFlags::kMutable}},
        {"num_shard_bits",
         {offsetof(struct LRUCacheOptions, num_shard_bits), OptionType::kInt,
          OptionVerificationType::kNormal, OptionTypeFlags::kMutable}},
        {"strict_capacity_limit",
         {offsetof(struct LRUCacheOptions, strict_capacity_limit),
          OptionType::kBoolean, OptionVerificationType::kNormal,
          OptionTypeFlags::kMutable}},
        {"high_pri_pool_ratio",
         {offsetof(struct LRUCacheOptions, high_pri_pool_ratio),
          OptionType::kDouble, OptionVerificationType::kNormal,
          OptionTypeFlags::kMutable}},
        {"low_pri_pool_ratio",
         {offsetof(struct LRUCacheOptions, low_pri_pool_ratio),
          OptionType::kDouble, OptionVerificationType::kNormal,
          OptionTypeFlags::kMutable}},
};

直接注册也未尝不可,直观,适合聚集写法

依赖dlopen也可以,不过属于杀鸡牛刀

如何判断一个数字是不是浮点数0?判断0正负 https://godbolt.org/z/jcqc38qqW

直接贴代码

#include <numeric>
#include <cmath>
#include <iostream>


class FloatingPointComparator {
private:
    static constexpr double DEFAULT_EPSILON = 1e-10;
    static constexpr double MIN_NORMAL = std::numeric_limits<double>::min();
    static constexpr double MAX_NORMAL = std::numeric_limits<double>::max();

public:
    // 基本的零值检查
    static bool isZero(double value) {
        return std::abs(value) < DEFAULT_EPSILON;
    }
    
    // 带自定义误差的零值检查
    static bool isZeroWithEpsilon(double value, double epsilon) {
        return std::abs(value) < epsilon;
    }
    
    // 相对误差检查
    static bool isZeroRelative(double value) {
        if (std::abs(value) < MIN_NORMAL) {
            return true;
        }
        return std::abs(value) < DEFAULT_EPSILON * std::max(1.0, std::abs(value));
    }
    
    // IEEE 754 特殊值检查
    static bool isSpecial(double value) {
        return std::isnan(value) || std::isinf(value);
    }
    
    // 判断是否为正负零
    static bool isExactZero(double value) {
        return value == 0.0 || value == -0.0;
    }
    
    // 综合判断
    static bool isEffectivelyZero(double value) {
        if (isSpecial(value)) {
            return false;
        }
        if (isExactZero(value)) {
            return true;
        }
        return isZeroRelative(value);
    }
};

class ZeroSignChecker {
public:
    static bool isNegativeZero(double value) {
        if (value != 0.0) return false;
         /*
        union {
            double d;
            uint64_t u;
        } u = {value};
        return (u.u >> 63) == 1;
        */   
        auto u = std::bit_cast<std::uint64_t>(value);
        // 检查符号位(最高位)
        return (u >> 63) == 1;
    }
    
    static bool isPositiveZero(double value) {
        if (value != 0.0) return false;
        /*
        union {
            double d;
            uint64_t u;
        } u = {value};
        return (u.u >> 63) == 0;
        */
        auto u = std::bit_cast<std::uint64_t>(value);
        
        // 检查符号位
        return (u >> 63) == 0;
    }
    static bool isPositiveZeroV2(double value) {
        return value == 0.0 && !std::signbit(value);
    }
    
    static bool isNegativeZeroV2(double value) {
        return value == 0.0 && std::signbit(value);
    }

    static bool isNegativeZeroCoreDump(double value) {
        if (value != 0.0) return false;
        return std::isinf(1.0 / value) && (1.0 / value < 0);
    }
    
    static bool isPositiveZeroCoreDump(double value) {
        if (value != 0.0) return false;
        return std::isinf(1.0 / value) && (1.0 / value > 0);
    }
};

// 使用示例
void testZeroSign() {
    double pzero = 0.0;
    double nzero = -0.0;
    
    std::cout << "Positive zero: " << ZeroSignChecker::isPositiveZero(pzero) << std::endl;
    std::cout << "Negative zero: " << ZeroSignChecker::isNegativeZero(nzero) << std::endl;
    std::cout << "Positive zero: " << ZeroSignChecker::isPositiveZeroV2(pzero) << std::endl;
    std::cout << "Negative zero: " << ZeroSignChecker::isNegativeZeroV2(nzero) << std::endl;
}

// 使用示例
void testFloatingPoint() {
    double values[] = {
        0.0,
        -0.0,
        1e-15,
        1e-10,
        std::numeric_limits<double>::min(),
        std::numeric_limits<double>::denorm_min(),
        std::numeric_limits<double>::quiet_NaN(),
        std::numeric_limits<double>::infinity()
    };
    
    for (double val : values) {
        std::cout << "Value: " << val << std::endl;
        std::cout << "Is zero? " << FloatingPointComparator::isEffectivelyZero(val) << std::endl;
        std::cout << "Is special? " << FloatingPointComparator::isSpecial(val) << std::endl;
        std::cout << "Is exact zero? " << FloatingPointComparator::isExactZero(val) << std::endl;
        std::cout << "-------------------" << std::endl;
    }
}

int main() { 
    testFloatingPoint();
    testZeroSign();
    return 0;
}

为什么 exit() 函数不是线程安全的? https://www.zhihu.com/question/2278762213/

主要原因 exit语义等同于从main 返回,会涉及到资源释放等相关流程,自然引入竞争问题

避免全局资源释放,使用quick_exit

另外直接列一下各种exit区别 https://learn.microsoft.com/en-us/previous-versions/6wdz5232(v=vs.140)

  • exit 执行完整的 C 库终止过程,终止进程,并向主机环境提供提供的状态代码。
  • _Exit 执行最少的 C 库终止过程,终止进程,并向主机环境提供提供的状态代码。
  • _exit 执行最少的 C 库终止过程,终止进程,并向主机环境提供提供的状态代码。
  • quick_exit 执行快速 C 库终止过程,终止进程,并向主机环境提供提供的状态代码。
  • _cexit 执行完整的 C 库终止过程并返回给调用方。不终止进程。
  • _c_exit 执行最少的 C 库终止过程并返回给调用方。不终止进程。

VC++中 log10(1e-23f) 向下舍入时,结果错误。如何解决? https://www.zhihu.com/question/1790209844/

msvc的log10f 和gcc libm的log10f行为不一样。大概实现算法有区别

两种结果都是符合标准的,毕竟round

互动环节

熬夜看了英雄联盟S14总决赛,BLG vs T1, 2:3 本来2:1很有机会,但

第四局第五局的faker真的发挥了200%的水平,逆转夺冠

我看的很难受。尤其是赛后很多人踩脸

我不知道为什么全华班追求冠军是一种过错

什么开香槟不谦逊都成了罪过,怎么给自己打气也要批评?

星际韩国包圆,李培楠也努力追求冠军不放弃

街霸日本包圆,曾卓君也努力追求冠军

dota有wings,就算lgd ti10打的气人也是追求过了

唯独lol,我是真无法理解有这么多喜欢狗仗人势的观众

这样的环境,真令人遗憾

也许这次就相当于dota ti8吧 大家记住了水人泼高地记住了on出乱送,然后顺便骂捞批捞底座赛区杂交赛区

真令人遗憾


上一期 下一期