【发布时间】:2016-01-06 09:42:20
【问题描述】:
在 Effective C++(第 3 版)中,第 2 项(首选 const、enum 和 inline 到 #define)中,类特定常量的代码段如下:
class GamePlayer {
private:
static const int NumTurns = 5; // constant declaration
int scores[NumTurns]; // use of constant
...
};
然后这本书说(用我自己的话来说)static const int NumTurns = 5; 不是一个定义,这通常是 C++ 对类成员的要求,除非它是一个从未使用过地址的静态整数常量。如果上述情况不适用于常量,或者编译器出于任何原因坚持定义,则应在实现文件中提供定义,如下所示:
const int GamePlayer::NumTurns; // definition of NumTurns; see
// below for why no value is given
根据这本书(也是我自己的话),定义中没有给出任何值,因为它已经在声明中给出了。
这让我以为我已经知道声明和定义的定义感到困惑(在问这个问题之前我在谷歌上仔细检查过):
- 为什么
static const int NumTurns = 5不是一个定义?NumTurns这里不是初始化为5的值吗,是不是声明和定义一起出现的时候才叫初始化? - 为什么
static整数常量不需要定义? - 为什么第二个代码 sn-p 在没有定义值的情况下被认为是定义,但包含该值的类内部的声明仍然不是一个(基本上回到我的第一个问题)?
- 初始化不是定义吗?为什么这里没有违反“唯一定义”规则?
我可能只是在这一点上感到困惑,所以有人可以从头开始重新教育我:为什么这两行代码声明和定义而不是另一行,那里有任何初始化实例?初始化也是定义吗?
致谢:代码 sn-ps 直接引用自书中。
编辑:额外引用What is the difference between a definition and a declaration?
- 一个声明引入了标识符和类型
- 定义实例化和实现
所以,是的……这似乎不是这里发生的事情。
编辑 2:我认为编译器可能会优化静态整数常量,方法是不将其存储在内存中,而只是在代码中内联替换它。但是如果使用NumTurns地址,既然实例化已经存在,为什么声明不自动变为声明+定义?
编辑 3: (此编辑与原始问题的关系不大,但仍然很突出。我把它放在这里,这样我就不需要为下面的每个答案复制粘贴到 cmets 中。请在 cmets 中回答我. 谢谢!)
感谢您的回答。现在我的头脑更清晰了,但编辑 2 的最后一个问题仍然存在:如果编译器在程序中检测到需要定义的条件(例如,程序中使用了&NumTurns),为什么不自动将static const int NumTurns = 5; 重新解释为声明和定义,而不是仅声明?它具有程序中其他任何地方的定义所具有的所有语法。
我来自学校的 Java 背景,并且不需要以上述方式为静态成员进行单独的定义。我知道 C++ 是不同的,但我想知道为什么上面是这样的。如果地址从不使用,则静态整数成员被内联替换,这对我来说更像是一种优化而不是基本功能,所以为什么我需要解决它(在条件不存在时提供单独的语句作为定义即使原始语句的语法足够了)而不是相反(编译器将原始语句视为定义,因为语法足够,所以需要它)?
【问题讨论】:
-
@juanchopanza 已编辑和澄清。
-
归结为包含类定义的翻译单元是否需要自己为常量分配内存,或者它是否信任其他翻译单元会创建一个包含该常量的对象,而当前翻译单元可以将其视为外部。只有当您有定义(无值)时,当前翻译单元才会在正在创建的对象中分配空间。这样,一旦链接,所有翻译单元都会访问同一个变量。
-
您对声明给出的默认值感到困惑,而不是定义。您也可以在定义中给出值,但您不能省略定义(这实际上使
NumTurns存在)。声明中的= 5只设置了一个default,它确实not 设置了一个值。定义 (const int GamePlayer::NumTurns;) 使用该默认值;它也可以提供非默认初始化。 -
@DevSolar 它确实设置了一个 value,因为该常量可以通过内联替换该值在类中使用。但是,是的,这个值在与类一起定义之前在外部(或用于地址)是不可用的。
-
Effective C++ 本身解释说(正如@TonyD 所说)只有 definitions 实际上会导致编译器为某些东西分配内存,但你不会'在您进行第二次编辑之前,您甚至都不会提及记忆。我同意这令人困惑,但这里的问题是您试图让迈耶斯的示例符合您对“定义”和“声明”,而不是试图理解并应用您正在阅读的书中给出的他的定义。
标签: c++ effective-c++