【问题标题】:global const var declared once, is it possible?global const var 声明一次,有可能吗?
【发布时间】:2021-02-12 18:46:09
【问题描述】:

我有一个头文件,其中包含我正在制作的 DLL 中需要的所有 const 值,例如:

// myHelpers.hpp
const int kMaxNumVoices = 16;
const int kMaxBeats = 32;
....

等等。在每个 .cpp 中包含 .hpp 后,我也可以在 std::array 定义中使用这些常量。

问题(理论上)是这将违反ODR,因为每个编译单元都会使用每个 var 的副本(即使它们是 const),对吧?

这可以接受吗?或者可以处理一些未定义的行为?如果它不可接受,那么正确的方法是什么?

【问题讨论】:

标签: c++ c++11 constants global one-definition-rule


【解决方案1】:

特别是当您打算将这些常量用作非类型模板参数时(如在std::array 中),最好的方法是将它们限定为constexpr

constexpr int kMaxNumVoices = 16;
constexpr int kMaxBeats = 32;

但是,为了不违反 ODR,您不得在 ODR 中使用它(例如,获取它的地址,请参阅 this thread 了解更多信息)。这基本上与适用于const-qualified 变量的限制相同。

一旦你可以将你的代码库迁移到 C++17,另外标记它们inline

constexpr inline int kMaxNumVoices = 16;
constexpr inline int kMaxBeats = 32;

【讨论】:

  • 不能用 constexpr 做这样的事情:constexpr float kLN2 = std::log(2.0f)
  • 没错,如果需要,您必须坚持使用const
【解决方案2】:

我认为像log2 这样的常量应该始终由文字定义...

不过不管怎样,C++17之后可以使用inline变量,如果在C++11中,可以使用未命名的命名空间:

namespace{
    int const kMaxNumVoices = 16;
}

这意味着这些常量是inline

inline 变量仅适用于每个单独的翻译单元,因此不要尝试修改它们并让其他翻译单元中的代码观察它。

【讨论】:

    猜你喜欢
    • 2021-09-21
    • 2014-04-25
    • 2021-05-16
    • 1970-01-01
    • 2011-11-29
    • 1970-01-01
    • 2014-10-24
    • 2019-07-12
    • 2011-11-23
    相关资源
    最近更新 更多