C++ Tips of the Week
文章平均质量分 75
翻译Google的C++ Tips of the Week。
-飞鹤-
喜欢音乐,喜欢文学,喜欢跑步,喜欢编程!
展开
-
本周小贴士#229:模板元编程的分级重载
既然你已经学会了这种令人很棒的能力,请记住要谨慎使用它。正如我们在absl::string_view重载中看到的那样,泛型编程很微妙,可能导致意想不到的结果。翻译 2024-08-30 19:54:24 · 89 阅读 · 0 评论 -
本周小贴士#227:小心空容器和无符号算术
正如风格指南所说,在C++中对无符号类型进行算术运算时要小心。记住,容器.size()产生一个无符号类型。偏好可以尽可能在局部验证正确性的代码。尽量使代码直接对应于底层意图。翻译 2024-04-18 18:13:22 · 59 阅读 · 0 评论 -
本周小贴士#224:避免使用vector.at()
在索引容器时,请注意我们处于哪种情况:索引是否是"按构造确定的",还是代码需要检测和处理无效的索引?在这两种情况下,我们都可以比使用基于异常的std::vector::at() API更好。类似的思考也适用于其他基于异常的API,如std::optional::value()和absl::StatusOr::value()(参见Tip#181)。对于非并发的C++代码中的错误处理,请优先进行"查看后跳转" - 然后,在检查了一切都正常之后,避免使用包含自身检查的API。翻译 2024-03-28 18:10:32 · 140 阅读 · 0 评论 -
本周小贴士#218:用FTADLE设计扩展点
这篇翻译讲述了在C++中关于扩展点机制的设计问题以及引入FTADLE(Friend Template with ADL Extension)模式来解决这些问题。文章首先提到了一些常见的扩展点机制,如虚函数、成员函数检查和模板特化,并指出它们各自存在的问题和局限性。接下来,文章详细介绍了FTADLE模式的设计原理和优势。通过使用友元函数模板和ADL(Argument-Dependent Lookup)机制,FTADLE模式可以实现可扩展性、灵活性和低耦合度。它能够避免类层次结构的僵硬性和对用户的依赖,同时翻译 2023-12-01 22:00:00 · 152 阅读 · 0 评论 -
本周小贴士#198:标签类型
作为TotW#198最初发表于2021年8月12日由Alex Konradi创作Foo既不可移动也不可复制,但它是可构造的,例如Foo f(1, 2);。这很棒,但是如果std::optional被声明为const,那么我们无法调用emplace()怎么办?等等,std::in_place是什么意思?如果我们查看std::optional的文档,可以看到其中一个重载函数接受std::in_place_t作为第一个参数,以及其他参数的列表。翻译 2023-10-05 17:34:24 · 145 阅读 · 0 评论 -
本周小贴士#188:注意智能指针函数参数
作为TotW#188最初发表于2020年12月10日作者:Krzysztof Kosiński这段代码有什么问题?函数 CanYouPetTheDog 不会影响其 dog 参数的所有权,然而它的函数签名要求将其存储在 std::shared_ptr 中。这样做创建了对特定所有权模型的不必要依赖,尽管函数内部并不需要。这种依赖性阻止调用者使用其他模型,如 std::unique_ptr 或在栈上构造对象。翻译 2023-09-06 19:15:00 · 149 阅读 · 0 评论 -
本周小贴士#187:std::unique_ptr 必须被移动
std::unique_ptr是一个指针,当std::unique_ptr本身被销毁时,它会自动销毁指向的任何对象。它存在的目的是作为类型系统的一部分来传递所有权(销毁资源的责任),并且是C++11中更有价值的新增功能之一。然而,std::unique_ptr经常被过度使用。一个好的检验方法是:如果它从未被std::unique_ptr移动到另一个std::unique_ptr,那么它可能不应该是std::unique_ptr。翻译 2023-07-28 12:11:45 · 122 阅读 · 0 评论 -
本周小贴士 #186:将函数放在未命名的命名空间中
文件局部函数简化了依赖关系并改善了局部性。非成员函数增加了封装性,简化了类定义,并使依赖关系更加明确。编写函数时,请考虑将其作为文件局部非成员函数,例如将其放在.cc文件的未命名命名空间中。翻译 2023-07-15 17:56:18 · 120 阅读 · 0 评论 -
本周小贴士#182:初始化你的整形变量
作为TotW#182最初发表于2020年7月23日“在做决定的瞬间,你能做的最好的事情是正确的事情,接下来最好的事情是错误的事情,而你能做的最糟糕的事情就是什么都不做。” ——西奥多·罗斯福C++很容易让变量未初始化,这非常危险,因为几乎对任何未初始化对象的访问都会导致未定义行为。默认初始化是其中一种形式,当变量没有指定初始值时发生,默认初始化并不总是初始化。翻译 2023-06-29 15:46:39 · 120 阅读 · 0 评论 -
本周小贴士#181:访问 StatusOr<T> 的值
作为TotW#181最初发表于2020年7月9日由Michael Sheely创作当需要访问 absl::StatusOr 对象中的值时,我们应该努力使该访问安全、清晰和高效。注意:本提示试图强调提供典型用例的指导,但并非详尽无遗。如果遇到边缘情况,请考虑本文中的建议和推理,并行使判断力。翻译 2023-06-06 20:38:57 · 216 阅读 · 0 评论 -
本周小贴士#180:避免悬空引用
与许多编程语言不同,C++缺乏必要的安全检查,以避免引用无效内存(即“悬空引用”)。您可以轻松地对已删除的对象指针进行解引用,或者跟随一个超出作用域的对象引用。即使是类类型也存在这种风险。重要的是,我们正在建立命名约定,围绕名称“view”和“span”表示“这是具有引用语义并可能悬空的对象”。像所有具有引用语义的类型一样,这些类型从不拥有它们指向的基础数据。每当您看到存储这些类型之一的实例时,请注意。翻译 2023-06-01 09:46:02 · 411 阅读 · 0 评论 -
本周小贴士#177:可赋值性与数据成员类型
作为TotW#177最初发表于2020年4月6日由Titus Winters创作在实现类型时,应先确定类型设计。将API优先于实现细节。这种情况的一个常见例子是类型可赋值性和数据成员的限定符之间的权衡。翻译 2023-05-25 22:06:38 · 86 阅读 · 0 评论 -
本周小贴士#176:优先返回值而不是输出参数
作为TotW#175最初发表于2020年3月12日由Etienne Dechamps创作。翻译 2023-05-22 12:40:32 · 175 阅读 · 0 评论 -
本周小贴士#175:C++14和C++17中字面常量的变化:
C++现在具有一些功能,可以使数字字面常量更易读。整型字面常量现在可以用二进制(0b00101010)表示,之前只支持十进制(42)、十六进制(0x2A)和八进制(052)。单引号(')可以作为数字分隔符,可以用来分组任何进制的数字字面常量(0xDEAD’C0DE)。浮点型字面常量可以用十六进制表示(0x2A0p-4)。翻译 2023-05-16 21:43:38 · 220 阅读 · 0 评论 -
本周小贴士#173:将参数包装在Option结构中
作为TotW#173最初发表于2019年12月19日由John Bandela创作它来了,没有包裹,盒子或袋子。他疑惑不解,一直疑惑到他的脑筋疼痛了——Dr. Seuss。翻译 2023-05-05 21:47:43 · 91 阅读 · 0 评论 -
本周小贴士#172:指定初始化器
作为TotW#171最初发表于2019年12月11日由Aaron Jacobs创作指定初始化器是 C++20 标准草案中的一种语法,用于以紧凑但易读且易维护的方式指定结构体的内容。除了语法更简洁之外,指定初始化器可在更多的上下文中使用。翻译 2023-04-23 12:48:32 · 160 阅读 · 0 评论 -
本周小贴士#171: 避免标志值
作为TotW#171最初发表于2019年11月8日由Hyrum Wright创作标志值是在特定上下文中具有特殊意义的值。除了-5外,int类型的每一个值都被记录为AccountBalance的有效返回值。直觉上,这感觉有点奇怪:调用方只应该检查-5特别吗?任何负数值是否可靠地表示“账户关闭”?当系统支持负余额并且需要调整API以返回负值时会发生什么?使用标志值会增加调用代码的复杂性。翻译 2023-04-19 22:21:48 · 98 阅读 · 0 评论 -
本周小贴士#168:内联变量
这仅适用于静态constexpr数据成员,而不适用于其他constexpr变量以及仅为静态const的数据成员。几乎每个在头文件中定义的全局变量都应标记为inline,并且通常也应是constexpr。如果它们没有标记为inline,则每个包含该头文件的.cc文件都将有一个单独的变量实例,这可能导致不易觉察的ODR(一个定义规则)违规。在头文件中使用函数的inline是一个紧密的类比;使用constexpr确保了初始化和销毁的安全性,使用内联则确保程序中只有一个kHelloWorld的副本。翻译 2023-04-17 18:55:13 · 111 阅读 · 0 评论 -
本周小贴士#166:当复制不是复制
从C++17开始,如果可能的话,对象将“就地”创建。public :// ... }这段代码会复制或移动BigExpensiveThing几次?在C++17之前,答案最多为三次:每个return语句一次,以及初始化thing时的一次。这是有一定道理的:每个函数可能会将BigExpensiveThing放在不同的地方,因此可能需要进行移动才能将值放在最终调用者想要的位置。但实际上,对象总是在变量thing中“就地”构造,没有执行移动操作,C++语言规则允许这些移动操作被省略以便进行此优化。翻译 2023-04-12 12:59:49 · 97 阅读 · 0 评论 -
本周小贴士#165:带有初始化器的if和switch语句
作为TotW#158最初发表于2019年8月17日由Thomas Köppe创作除非你使用条件控制流,否则你可以停止阅读了。翻译 2023-04-07 13:01:40 · 138 阅读 · 0 评论 -
本周小贴士#149:传递std::optional参数
std::reference_wrapper具有令人意想不到的微妙语义,使其难以理解和安全使用。例如,标准库中的各种实用程序特别处理它,使它的行为不同于普通值或引用。std::optional比仅仅使用cosnt Foo*要笨重和冗长。翻译 2023-04-02 22:11:18 · 236 阅读 · 0 评论 -
本周小贴士#161:好的本地变量和坏的本地变量
本地变量很好,但可能会被过度使用。我们通常可以通过将它们的使用限制在提供特定好处的情况下来简化代码。翻译 2023-03-22 20:55:24 · 90 阅读 · 0 评论 -
每周小贴士#158:Abseil关联窗口和contains()
作为TotW#158最初发表于2019年1月3日由James Dennett创作"我不能包含我自己“——伯特兰·罗素。翻译 2023-03-09 20:56:17 · 224 阅读 · 0 评论 -
每周小贴士#153:不要使用using指令
作为TotW#153最初发表于2018年7月17日由Roman Perepelitsa和Ashley Hedberg创作我认为使用指令(using-directives)就像是定时炸弹,对于使用它们的人和语言系统都是如此。——Ashley Hedberg(向沃伦·巴菲特致歉)翻译 2023-03-03 15:12:31 · 521 阅读 · 0 评论 -
每周小贴士#152:AbslHashValue和你
作为TotW#152最初发表于2018年6月21日由Matt Kulukundis创作我喜欢莫扎特,但我经常把它搞得一团糟。——西蒙·拉特ABSL :: HASH框架[https://abseil.io/docs/cpp/guides/hash]现在是swisstable hash表的默认哈希实现(absl :: absl :: {flat,node}hash})。通过此框架的所有类型可以自动作为Swisstables中的键使用。翻译 2023-02-15 20:31:05 · 213 阅读 · 0 评论 -
每周小贴士#149:对象生命周期与=delete
尝试结合使用右值引用或引用限定符=delete来提供更“用户友好”的 API,强制执行生命周期或防止优化问题是很吸引人的。实际上,这些通常是不好的吸引。生存期要求比 C++ 类型系统可以表达的要复杂得多。API 提供者很少能预测其 API 的每一次未来有效使用。避免这些类型的=delete技巧可以使事情变得简单。翻译 2023-01-31 01:24:30 · 113 阅读 · 0 评论 -
每周小贴士#148:重载集
作为TotW#148最初发表于2018年5月3日由Titus Winters创作使用电气信息的影响之一是我们习惯性地生活在信息过载状态下。总有更多超出您所能应付的。- 马歇尔·麦克卢汉我认为,C++风格指南中最强大,最有见解的句子之一是:“只有在查看调用点的读者可以很好的了解什么正在发生,而不必首先弄清楚哪个重载被调用,才使用重载函数(包括构造函数)”。从表面上看,这是一个非常简单的规则:仅用于重载不会引起读者的迷惑。但是,这种后果实际上是相当重要的,并涉及现代API设计中的一些有趣的问题。翻译 2022-11-11 18:19:31 · 148 阅读 · 0 评论 -
本周小贴士#147:负责地使用穷举witch语句
使用 -Werror 编译器标志,如果枚举的任何枚举数没有相应的大小写,则没有默认标签的枚举类型值的 switch 语句将无法编译。这有时被称为穷举或无默认 switch 语句。穷举switch 语句是确保在编译时显式处理给定枚举的每个枚举值的良好构造。但是,当变量(合法!枚举的所有者保证不会添加新的枚举数,当添加新的枚举值时,枚举的所有者愿意并且能够修复我们的代码(例如,枚举定义是同一项目的一部分),...翻译 2022-08-31 14:21:01 · 260 阅读 · 0 评论 -
本周小贴士#146:默认vs值初始化
创建对象时,它们可能会被初始化或未初始化。未初始化的对象阅读起来并不安全,但了解对象何时未初始化并非易事。首先要了解的是正在构建的类型是标量、聚合还是其他类型。标量类型可以被认为是一种简单类型:整数或浮点算术对象;一个指针;一个枚举;指向成员的指针;nullptr_t。聚合类型是数组或普通类(只有公共的非静态数据成员,没有用户提供的构造函数,没有基类,没有虚拟成员函数,也没有默认成员初始化器)。影响实例是否已初始化为可安全读取的值的另一个因素是它是否具有显式初始化程序。.........翻译 2022-08-17 11:15:38 · 253 阅读 · 0 评论 -
本周小贴士#144:关联容器中的异构查找
关联容器使用一个关键字来关联一个元素。插入或从容器中查找元素需要等效键。通常,容器要求键是特定类型的,这会导致调用处的效率低下,需要在接近等效的类型(如 std::string 和 absl::string_view)之间进行转换。为了避免这种不必要的工作,一些容器提供了异构查找。此功能允许调用者传递任何类型的键(只要用户指定的比较器函子支持它们)。有关 STL 容器中此功能的示例,请参见 std::map::find。...翻译 2022-08-14 11:45:19 · 236 阅读 · 0 评论 -
本周小贴士#143:C++11 删除的函数(= delete)
一般来说,接口通常定义了可以调用的操作集。然而,有时我们可能想要表达相反的意思明确定义一组不应使用的操作。例如,禁用拷贝构造函数和拷贝赋值运算符是限制特定类型的拷贝语义的常用方法。提供一个仅由运行时检查组成的虚拟定义。使用可访问性控件(受保护/私有)使功能不可访问。声明函数,但有意省略定义。从C++11开始将函数显式定义为“已删除”。C++11之前的技术范围从运行时检查(#1)到编译时(#2)或链接时(#3)诊断。虽然经过实战验证,但这些技术远非完美private。...翻译 2022-07-27 22:53:51 · 2026 阅读 · 0 评论 -
每周小贴士#142:多参数构造函数和explicit
在C++11之前,explicit关键字仅对可以使用单个参数调用的构造函数有意义,并且我们的风格指南要求将其用于此类构造函数,以免它们充当“转换构造函数”。该要求不适用于多参数构造函数。事实上,风格指南曾经不鼓励对多参数构造函数使用显式,因为它没有任何意义。情况不再如此。在C++11中,显式对于从花括号列表进行复制初始化变得有意义,例如在使用f({1,2})调用函数voidf(stdpair)或初始化变量bad时,使用std。等一下!std。...翻译 2022-07-24 21:26:23 · 396 阅读 · 0 评论 -
本周小贴士#141:注意隐式转换到bool
作为TotW#141最初发表于2018年1月19日由Samuel Freilich创作在解引用之前检查指针是否为空来避免崩溃和错误很重要。这可以通过两种方式完成:鉴于foo是一个指针,这两个条件具有相同的语义,但后面的类型检查更严格点。在C++中,许多类型都可以隐式转换为bool,当指向的类型本身转换为bool时需要额外注意。考虑以下代码,它可能具有两个截然不同的含义:这份代码更清晰:这两种样式在 Google C++ 代码中都是可接受的。 所以当底层类型不能隐式转换为 bool 时,遵循周围代码翻译 2022-07-02 17:10:49 · 406 阅读 · 0 评论 -
本周小贴士#140:常量:安全习语
作为TotW#140最初发表于2017年11月8日由Matt Armstrong创作在 C++ 中表达常量的最佳方法是什么? 您可能知道这个词在英语中的含义,但是在代码中很容易错误地表达这个概念。 在这里,我们将首先定义一些关键概念,然后列出安全技术。 对于好奇的人,我们随后会更详细地了解可能出现的问题,并描述 C++17 语言功能,该功能使表达常量更容易。“C++ 常量”没有正式的定义,所以让我们提出一个非正式的定义。综上所述,让我们将常量称为始终计算为相同值的变量或函数。 这里有几个关键概念。当我们说我翻译 2022-06-25 19:37:05 · 217 阅读 · 0 评论 -
本周小贴士#136:无序容器
TotW#136最初发表于2017年6月23日由Matt Kulukundis创作“有时,当材料真的很好时,你会对自己寄予期望,以使其成为最好的节目。你不只是提供规则的哈希,接着做你的工作,然后回家。”-彼得.丁拉基长话短说,有关官方最新的推荐,请看https://abseil.io/docs/cpp/guides/container。本贴士介绍新类型,但不是规范的参考。城镇出现了一个新的关联容器系列。他们自夸提高效率并提供早于C++17的访问。他们也对开发者提供直接控制其实现和默认的哈希函数,这对于翻译 2022-06-18 20:52:24 · 1244 阅读 · 0 评论 -
本周小贴士#135:测试约定而不是实现
作为TotW#135最初发表于2017年6月5日由James Dennett创作“如果你有一个真正的朋友,那么你拥有的不仅仅是你所拥有的”——托马斯·富勒C++有一个使用公有的,保护的,私有的和友元的详细访问控制机制。测试代码有它自己使用这些装置的规则,GoogleTest使用它的FRIEND_TEST宏来扩充它们。使用FRIEND_TEST应该是最后的手段,而不是优先选项。我们编写测试来发现组件约定实现中的错误,或者让我们有足够的信心相信这里没有此类错误。在使用测试驱动开发(TDD)时,我们还编写测试来帮翻译 2022-06-05 18:29:13 · 220 阅读 · 0 评论 -
本周小贴士#134:make_unique与私有构造函数
作为totw#134最初发表于2017年5月10日由谷歌工程师Yitzhak Mandelbaum创作因此,你阅读了小贴士#126并准备留下一些新的东西。一切都是正常的,直到你尝试使用absl::make_unique并使用私有构造函数去构造对象,但是编译失败。让我们看一下这个问题的一个具体示例,以便理解哪里出了问题。然后,我们可以讨论一些解决方案。示例:制造小部件你正在定义一个类来展示小部件。每个小部件都有一个标识符,这些标识符受某些约束。为了确保一直满足这些约束,你将Widget类的构造函数声明翻译 2022-05-30 19:29:33 · 1317 阅读 · 0 评论 -
本周小贴士131:特殊成员函数和`= default`
作为totw#131最初发表于2017年3月24日由James Dennett (jdennett@google.com)创作从一开始,C++ 就支持一些所谓的特殊成员函数的编译器声明版本:默认构造函数、析构函数、复制构造函数和复制赋值运算符。 C++11 向列表添加了移动构造和移动赋值,并添加了语法(=default 和 =delete)以控制何时声明和定义这些默认值。=default 有什么作用,我们为什么要使用它?写 =default 是我们告诉编译器“你通常会为这个特殊成员函数做的事情”的方翻译 2022-05-28 18:42:59 · 320 阅读 · 0 评论 -
本周小贴士#130:命名空间命名
作为totW#130最初发表于2017年2月17日由Titus Winters (titus@google.com)创作命名的准确性夺去了所见的唯一性——皮埃尔·勃纳尔。Google C++ Style Guide 的最早提交包含许多人仍在使用的命名空间命名指南。 粗略地说,这可以概括为“命名空间源自包路径”。 紧跟 Java 的包命名要求,这很有意义:我们希望能够唯一标识 C++ 中的符号,并且我们希望命名空间选择具有唯一性和一致性。实际上,我们并没有。 我们只是将近十年都没有意识到。名称查找翻译 2022-05-21 17:51:01 · 157 阅读 · 0 评论 -
本周小贴士#126: ‘make_unique‘是新的‘new‘
作为totW#126最初发表于2016年12月12日由James Dennett (jdennett@google.com)基于Titus Winters (titus@google.com)的邮件列表创作随着代码库的扩展,越来越难以了解你依赖的每件事的细节。需要深入的知识无法扩展:我们必须依靠接口和契约来知道代码是正确的,无论是在写还是审查时。在许多情况下,类型系统可以用一种通用的方式来提供这些契约。类型系统契约使用的一致性,通过识别在堆上分配的对象存在潜在风险分配或所有权转移的位置,可以更轻松地编写翻译 2022-04-25 20:40:47 · 930 阅读 · 0 评论