Google C++每周贴士 #103: Flag是全局变量

本文讨论了为何不应在头文件中声明全局变量,特别是Abseil Flags,因为它们可能导致未定义行为。建议尽量避免使用flag,如果必须使用,应将其设计得如同全局变量般谨慎处理,并在定义所在的文件中声明。考虑将flag设为私有静态变量,或者通过函数访问。定义flag时使用宏以避免名称冲突。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

(原文链接:https://abseil.io/tips/103 译者:clangpp@gmail.com)

每周贴士 #103: Flag是全局变量

.cc文件的全局作用域定义flag。在相应的.h文件里声明之(最多一次)。

为什么要在头文件中声明东西?

对我们大部分人来说,使用头文件是本能反应,所以我们也许忘记了它们为什么被使用:

  1. 在头文件中声明东西,可以使其很容易被其他地方#include。整个程序看到的都是同样的声明。
  2. 在定义了相同实体的.cc中包含该头文件,确保了定义与声明相匹配。
  3. 头文件可以作为程序包的公开API。除了程序包的公开API,使用其他任何东西都容易出锅。
  4. 包含头文件,而不是重新声明实体,既方便工具又方便人来进行依赖分析。

Abseil Flags和其他任何全局变量一样脆弱

你可以在没有链接错误的情况下把这货搞砸。首先,在一个.cc文件中放进如下代码:

// 在一个.cc文件中定义--my_flag。
ABSL_FLAG(std::string, my_flag, "", "My flag is a string.");

然后把下面这个(错误的)flag声明放进另一个.cc文件(比如测试文件):

// 声明错误:类型应该是std::string。
extern absl::Flag<int64> FLAGS_my_flag;

这段程序不合规范,而且发生任何情况都是未定义行为的结果。在我的测试程序中,这段代码编译通过,链接成功,然后在访问该flag的时候崩溃了。

建议

像设计全局变量那样设计命令行flag。

  1. 尽可能避免flag。参考http://abseil.io/tips/45。
  2. 如果你用flag让测试更好写,但永远不会在产品代码里设置它,那请考虑在你的类里加入测试专用(test-only)的API。
  3. 考虑将flag当做私有静态变量。如果别的程序包需要访问它们,那就把它们包装成函数。
  4. 在全局作用域中定义flag,而不是在命名空间里,这样flag名字重复的时候就能收到编译错误。
  5. 如果一个flag在多个文件中被访问,那就在它的定义所对应的.h文件中声明它。
  6. ABSL_FLAG(type, ...)宏来定义flag。

结论

Flag是全局变量。用的时候要慎重。像对待其他任何全局变量那样使用和声明它们。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值