什么时候应该使用静态数据成员与 const 全局变量?

When should I use static data members vs. const global variables?

声明 const 全局变量已证明对确定 API 的某些功能参数很有用。例如,在我的 API 上,数值精度运算符的最小阶数是 2;因此,我声明:

const int kDefaultOrderAccuracy{2};

作为全局变量。将其设为描述这些运算符的 类 的 static const public 数据成员会更好吗?一般来说,什么时候选择一个比另一个更好?

我的猜测是: const 每次使用时根据数据值的大小占用内联内存,例如“mov ah, const value”,这可以是一个非常短的命令,总体而言,总体而言,基于输入值。 而静态值占用整个完整的数据类型,通常是 int,无论对于每个静态的当前系统可能是什么,可能更多,加上它可能需要一个完整的内存访问值来访问数据,例如 mov ah, [memory pointer ],这通常是系统上 int 的大小,每次使用(完整的 class 可能会更复杂)。但是 static 仍然被声明为 const,因此它的行为可能与普通的 const 类型相同。

上下文总是很重要。

  • 回答这样的问题。
  • 也为自己命名。

如果您作为 reader(合作编码者)需要猜测标识符的含义,您会开始寻找更多上下文,这可能会通过 API 文档得到支持,该文档通常包含在体面的IDE。但是,如果您没有提供非常棒的 API 文档(我从您的问题中读到了这一点),您获得的唯一上下文就是查看声明的位置。

在这里,您可能对包含的库、子目录、文件、命名空间或 class 的名称感兴趣,最后对所使用的类型也很重要。

如果kDefaultOrderAccuracy,我看到很多上下文编码(默认顺序Accuracy),其中 Order 可能与销售或排序相关,而 k 编码不相关对我说什么。只是为了让您从不同的角度看待您的实际问题。 C/C++ 标识符的语法很差:它们仅限于复合词的规则。

全局标识符的这种限制是我主要避免使用全局变量,甚至是常量,有时甚至是类型的最重要原因。如果它的含义仅限于给定的上下文,请在此上下文中定义正确的事物。有时您首先必须 创建此上下文

您的解释包含一些未使用的上下文:

  • 数值运算符
    • 最小精度(顺便说一句:最小并不意味着默认

将定义放入正确的问题 class 与为全局找到正确位置的问题没有太大区别:您必须 find/create 正确的头文件 (and/or命名空间)。

作为旁注,您可能有兴趣了解 enum can be used to get cheap compile-time constants, and enums can also be placed into classes (or namespaces). Also a scoped enumeration 也是您在引入全局常量之前应该考虑的一个选项。与封闭的 class 定义一样,:: 是一种标点符号,它分隔多个 _ 或词内 caseChange.

附录:

如果您有兴趣为您的操作提供可以被用户覆盖的有用默认行为,default arguments could be an option. If your API provides operators, you should study how the input/output manipulators 标准 I/O 流工作。

const int kDefaultOrderAccuracy{2};

是静态变量的声明:kDefaultOrderAccuracy有内部链接。将具有内部链接的 名称放在 header 中显然是一个极其糟糕的主意 ,这使得在具有外部链接的其他代码中极易违反单一定义规则 (ODR)相同或其他 header,特别是在内联或模板函数的 body 中使用名称时:

里面 f.hpp:

template <typename T>
const T& max(const T &x, const T &y) {
  return x>y ? x : y;
}

inline int f(int x) {
  return max(kDefaultOrderAccuracy, x); // which kDefaultOrderAccuracy?
}

一旦您在两个 TU(翻译单元)中包含 f.hpp您就违反了 ODR,因为定义不是唯一的,因为它使用了命名空间静态变量:定义指定的 kDefaultOrderAccuracy object 取决于编译它的 TU。

class 的静态成员具有外部链接:

struct constants {
  static const int kDefaultOrderAccuracy{2};
};

inline int f(int x) {
  return max(constants::kDefaultOrderAccuracy, x); // OK
}

程序中只有一个constants::kDefaultOrderAccuracy

你也可以使用命名空间级别的全局常量objects:

extern const int kDefaultOrderAccuracy;