9

这个风格指南对我很有用,但我遇到了规则 #5:

通常,应尽量减少使用此类常量。在许多情况下,将值作为方法实现是更好的选择:

int getMaxIterations() // NOT: MAX_ITERATIONS = 25
{
    return 25;
}

我从风格的角度理解这个推理:你不仅取消了“大喊大叫”的常量声明,而且还减少了正在使用的语言结构的数量(如果这是不正确的术语,请原谅我),使程序更容易理解。

但是,这种方法是否会对编译器产生负面影响,或者现代编译器(或者实际上是较旧的编译器..)能够足够提前确定您的 getMaxIterations 函数每次都返回相同的数字?

确实,再三考虑,编译器是否甚至需要向前看?样式指南建议方法方法比使用常量值更好,我猜这是正确的,因为“常量”值在其在任何范围内的使用完成后不需要保存在内存中?

总之,我的问题是:不鼓励使用常量值,如果是,为什么?

(对于奖励积分,将常量值声明为方法和常量之间有什么技术区别?)

4

4 回答 4

4

这是内联的大多数编译器。

话虽如此,风格指南是有道理的。它说而不是这样做:

#define FOO_MAX_ITERATIONS 25
struct Foo {
  void do_it() { for(int i = 0; i < FOO_MAX_ITERATIONS; i++) iterate(); }
};

应该是这样的:

struct Foo {
  int getMaxIterations() { return 25; }
  void do_it() { for(int i = 0; i < getMaxIterations(); i++) iterate(); }
};

正如您所看到的,从长远来看,它更加一致和可读,并且有利于未来的设计,例如当您从类继承时。稍后,您可能希望在运行时修改 getMaxIterations(),而不必像 #define FOO_MAX_ITERATIONS someMethod() 那样做丑陋的 hack。

如果您使用任何健全的 C++11 编译器(即不是 Visual Studio),则应另外声明此类函数:

struct Foo {
  constexpr int getMaxIterations() { return 25; }
  void do_it() { for(int i = 0; i < getMaxIterations(); i++) iterate(); }
};

请注意那里的 getMaxIterations() 声明中的 constexpr 。这告诉 C++11 编译器它是一个“常量表达式”,并且可以在编译时进行评估。通过这样做,它可以在编译之前直接将 getMaxIteratsion() 替换为 25,其中包括许多其他事情,例如允许您在其他编译时声明中使用它。

于 2012-09-26T20:45:32.153 回答
4

原因之一是 Bertrand Meyer 所说的“统一参考原则”(IIRC)。

他以银行账户和当前余额为例。这应该是数据成员还是函数/方法?Meyer 认为,在软件项目的整个生命周期中,这种类型的决策可能会发生多次变化。因此,即使余额当前表示为数据成员,您也应该将其包装在 getter 中。然后,即使实现必须更改,接口也不必更改......因此此类的客户端与实现更改隔离。

换句话说,即使现在这是一个常数,您可能会发现自己处于需要计算的点。

而且,正如其他人所指出的那样,任何现代编译器(希望)都足够聪明,它们将内联方法实现,并且您不会因为将其作为方法而招致性能损失。

于 2012-09-26T20:51:09.253 回答
3

不,事实上,这是鼓励的。之前的编译器constexpr(有很多,甚至是最新的 MSVC)不能将函数调用用作常量值。

std::array<int, getMaxIterations()> arr; // bad
std::array<int, MaxIterations> arr; // fine

那个指南是一大堆错误。考虑 44

类的部分必须按公有、受保护和私有 [2][3] 排序。必须明确标识所有部分。不适用的部分应省略。

这是完全错误的。通常需要将它们交错,因为公共 API 依赖于私有的东西。这种严格的顺序禁止了几种 API,纯粹是因为声明顺序。一个简单的例子是你返回一个私有类型——通常用于代理对象、表达式模板等,或者公共方法的实现依赖于私有模板方法,在使用它之前必须完全定义。

于 2012-09-26T20:46:00.067 回答
0

声明一个常量值和以本样式指南建议的方式使用方法之间有一个巨大的区别。

方法声明:

int getMaxIterations()
{
  return 25;
}

意味着获取 getMaxIterations 的值可以修改调用该方法的对象的状态。这意味着您无法了解 const 对象的最大迭代值是多少。这也意味着在多线程环境中调用该方法可能是不安全的。这显然是不正确的,方法应该声明为:

int getMaxIterations() const;
于 2012-09-26T21:47:14.863 回答