当前位置:网站首页>本周小贴士#141:注意隐式转换到bool
本周小贴士#141:注意隐式转换到bool
2022-07-07 15:39:00 【-飞鹤-】
作为TotW#141最初发表于2018年1月19日
由Samuel Freilich创作
两种空指针检查
在解引用之前检查指针是否为空来避免崩溃和错误很重要。这可以通过两种方式完成:
if (foo) {
DoSomething(*foo);
}
if (foo != nullptr) {
DoSomething(*foo);
}
鉴于foo是一个指针,这两个条件具有相同的语义,但后面的类型检查更严格点。在C++中,许多类型都可以隐式转换为bool,当指向的类型本身转换为bool时需要额外注意。
考虑以下代码,它可能具有两个截然不同的含义:
bool* is_migrated = ...;
// 这是在检测is_migrated是否为空,或者真实意图是校验*is_migrated为真呢?
if (is_migrated) {
...
}
这份代码更清晰:
// 看起来像是对一个bool*的空指针进行检查
if (is_migrated != nullptr) {
...
}
这两种样式在 Google C++ 代码中都是可接受的。 所以当底层类型不能隐式转换为 bool 时,遵循周围代码的风格。 如果所讨论的值是像 std::unique_ptr 这样的“智能指针”,则语义和权衡是相同的。
可选值和作用域分布
可选(例如 absl::optional)值呢? 他们值得更仔细的考虑。
例如:
absl::optional<bool> b = MaybeBool();
if (b) {
... } // 当函数返回absl::optional(false)时发生了什么?
将变量声明放在 if 语句的条件中会限制变量的作用域,但该值会隐式转换为布尔值,因此可能无法明确测试哪个布尔属性。
以下代码的意图更清楚:
absl::optional<bool> b = MaybeBool();
if (b.has_value()) {
... }
请注意,实际上,上面的代码片段是等价的:absl::optional 到 bool 的转换只查看 optional 是否已满,而不是查看其内容。 读者可能会发现 optional(false) 为 true 有悖常理,但很明显 optional(false) 有一个值。 同样,当底层类型可以隐式转换为 bool 时,需要格外小心。
可选返回值的一种模式是将变量声明放在 if 语句的条件中。 这限制了变量的范围,但涉及到布尔的隐式转换:
if (absl::optional<Foo> foo = MaybeFoo()) {
DoSomething(*foo);
}
注意:在 C++17 中,if 语句可以包含初始化器,因此可以限制声明的范围,同时避免隐式转换:
if (absl::optional<Foo> foo = MaybeFoo(); foo.has_value()) {
DoSomething(*foo);
}
类布尔枚举
假设您已经采纳了技巧 #94 的建议,并决定在函数签名中使用枚举而不是 bool,以便在调用站点获得更好的可读性。 这种重构可能会在函数定义中引入隐式转换:
void ParseCommandLineFlags(
const char* usage, int* argc, char*** argv,
StripFlagsMode strip_flags_mode) {
if (strip_flags_mode) {
// 哪个值又是真呢?
...
}
}
您可以通过用显式比较替换隐式转换来获得额外的清晰度:
void ParseCommandLineFlags(
const char* usage, int* argc, char*** argv,
StripFlagsMode strip_flags_mode) {
if (strip_flags_mode == kPreserveFlags) {
...
}
}
总结
总之,注意隐匿转换为bool可能是不清楚的,因此考虑编写更显式的代码:
- 将指针类型与 nullptr 进行比较(特别是如果指向的类型可以隐式转换为 bool)。
- 使用诸如 absl::optional::has_value() 之类的布尔函数测试容器是否为空(特别是如果包含的类型可以隐式转换为 bool)。 对 if 使用可选的初始化形式来限制变量的范围(提示 #165)。 不过请记住只调用接口,不要获取 value() 或 has_value() 的地址。 testing::Optional 匹配器可以帮助测试。
- 将枚举与特定值进行比较。
更详细参考:Contextual conversions
边栏推荐
- LeetCode 1477. Find two subarrays with sum as the target value and no overlap
- [Seaborn] combination chart: facetgrid, jointgrid, pairgrid
- Nerf: the ultimate replacement for deepfake?
- LeetCode 300. Daily question of the longest increasing subsequence
- Devops' operational and commercial benefits Guide
- 【网络攻防原理与技术】第7章:口令攻击技术 第8章:网络监听技术
- 赋能智慧电力建设 | 麒麟信安高可用集群管理系统,保障用户关键业务连续性
- LeetCode 890(C#)
- Sator推出Web3游戏“Satorspace” ,并上线Huobi
- AI来搞财富分配比人更公平?来自DeepMind的多人博弈游戏研究
猜你喜欢
麒麟信安携异构融合云金融信创解决方案亮相第十五届湖南地区金融科技交流会
[image sensor] correlated double sampling CDs
【网络攻防原理与技术】第1章:绪论
Is AI more fair than people in the distribution of wealth? Research on multiplayer game from deepmind
Reflections on "product managers must read: five classic innovative thinking models"
NeRF:DeepFake的最终替代者?
How to add aplayer music player in blog
Seaborn数据可视化
Sator launched Web3 game "satorspace" and launched hoobi
SlashData开发者工具榜首等你而定!!!
随机推荐
LeetCode 535(C#)
Smart logistics platform: make overseas warehouses smarter
专精特新软件开发类企业实力指数发布,麒麟信安荣誉登榜
LeetCode 497(C#)
Flask搭建api服务
【饭谈】Web3.0到来后,测试人员该何去何从?(十条预言和建议)
The mail server is listed in the blacklist. How to unblock it quickly?
LeetCode 1696. Jumping game VI daily question
Lex & yacc of Pisa proxy SQL parsing
With the latest Alibaba P7 technology system, mom doesn't have to worry about me looking for a job anymore
L1-025 正整数A+B(Lua)
mysql官网下载:Linux的mysql8.x版本(图文详解)
Proxmox VE重装后,如何无损挂载原有的数据盘?
SIGGRAPH 2022最佳技术论文奖重磅出炉!北大陈宝权团队获荣誉提名
Sator推出Web3遊戲“Satorspace” ,並上線Huobi
Share the latest high-frequency Android interview questions, and take you to explore the Android event distribution mechanism
Linux 安装mysql8.X超详细图文教程
Devops' operational and commercial benefits Guide
L1-028 判断素数(Lua)
L1-019 谁先倒(Lua)