C++ 中文周刊 2024-11-03 第171期
公众号
点击「查看原文」跳转到 GitHub 上对应文件,链接就可以点击了
qq群 点击进入 满了加这俩 729240657 866408334
欢迎投稿,推荐或自荐文章/软件/资源等,评论区留言
本期文章由 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出乱送,然后顺便骂捞批捞底座赛区杂交赛区
真令人遗憾