-
Notifications
You must be signed in to change notification settings - Fork 22
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
b29d065
commit ad11b49
Showing
2 changed files
with
303 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,300 @@ | ||
--- | ||
layout: post | ||
title: 第171期 | ||
--- | ||
# C++ 中文周刊 2024-11-03 第171期 | ||
|
||
|
||
[周刊项目地址](https://github.com/wanghenshui/cppweeklynews) | ||
|
||
公众号 | ||
|
||
<img src="https://wanghenshui.github.io/cppweeklynews/assets/code.png" alt="" width="30%"> | ||
|
||
点击「查看原文」跳转到 GitHub 上对应文件,链接就可以点击了 | ||
|
||
qq群 [点击进入](https://qm.qq.com/q/6NGizNPyG4) 满了加这俩 729240657 866408334 | ||
|
||
[RSS](https://github.com/wanghenshui/cppweeklynews/releases.atom) | ||
|
||
欢迎投稿,推荐或自荐文章/软件/资源等,评论区留言 | ||
|
||
本期文章由 HNY 赞助 在此表示感谢 | ||
|
||
本期内容较少,掺杂一些互动 | ||
|
||
--- | ||
|
||
## 资讯 | ||
|
||
标准委员会动态/ide/编译器信息放在这里 | ||
|
||
[编译器信息最新动态推荐关注hellogcc公众号 本周更新2024-10-30 第278期 ](https://mp.weixin.qq.com/s/NSuihKy3ku3h00FnwO2PxQ) | ||
|
||
|
||
## 文章 | ||
|
||
### [How useful is the hint passed to the std::unordered_… collections? ](https://devblogs.microsoft.com/oldnewthing/20241028-00/?p=110428) | ||
|
||
|
||
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 | ||
|
||
我就不贴代码了,脑补一下就有了 | ||
|
||
- 直接注册也可以,比如 | ||
|
||
```cpp | ||
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 | ||
|
||
直接贴代码 | ||
|
||
```cpp | ||
#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 ti10吧 大家记住了水人泼高地记住了on出乱送,然后顺便骂捞批捞底座赛区杂交赛区 | ||
真令人遗憾 | ||
--- | ||
[上一期](https://wanghenshui.github.io/cppweeklynews/posts/170.html) [下一期](https://wanghenshui.github.io/cppweeklynews/posts/172.html) |