C++中声明和变量定义之间有什么区别?

Ujj*_*yan 18 c++

我的问题源于Scott Meyers 研究Effective C++.在该书的第二项中,写下如下:

要将常量的范围限制为类,必须使其成为成员,并且为了确保最多只有一个常量副本,必须使其成为静态成员.

这是正确的写.然后立即给出以下示例:

class GamePlayer {
private:
    static const int NumTurns = 5;
    int scores[NumTurns];
    ....
  };
Run Code Online (Sandbox Code Playgroud)

然后写下以下示例:

你在上面看到的是一个声明,而不是NumTurns的定义.

我的第一个问题是:这个陈述的含义是什么?

紧接着提到以下内容:

通常C++要求您为所使用的任何内容提供定义,但是静态和整数类型的类特定常量(例如 - 整数,字符,bools)是一个例外.只要您不接受他们的地址,您就可以声明它们并在不提供定义的情况下使用它们.如果您确实将类的地址设为常量,或者即使您没有使用该地址,您的编译器也错误地坚持定义,您提供了一个单独的定义,如下所示: const int GamePlayer::Numturns; //definition of NumTurns

为什么现在它是一个定义而不是声明?

我理解函数上下文中的差异,但在常规变量的上下文中不理解它.此外,有人可以扩展作者的意思

...如果你确实把一个类的地址定为常数,或者如果你的......部分引用了上面引用的段落?

PS:我是C++的新手.

Col*_*mbo 8

与函数一样,变量可以具有"纯粹声明性"声明和实际定义.你很困惑,因为之前你可能没有遇到过很多纯变量声明.

int i; // Definition
extern int i, j; // (Re)declares i, and declares j
extern int j = 0; // Defines j (confusing, eh?)
Run Code Online (Sandbox Code Playgroud)

正如您习惯使用函数一样,定义是声明,但并非所有声明都是定义.§3.1/ 2读

声明是一个定义,除非它在类定义(9.2,9.4)中声明了静态数据成员,

因此,类内静态数据成员声明永远不会定义它们声明的变量.但是,有时候,变量定义不一定存在.当你可以直接使用它的值而不需要变量运行时存在时就是这种情况.

在技​​术术语中,只要静态数据成员(或任何实体)不是"使用过的",就不必定义它.所有实体的使用频率在§3.2/ 3中定义:

一种可变x显示其名称为潜在评估表达 exODR使用的ex除非施加左值到右值转换(4.1),以x产率常量表达式(5.20),其不调用任何非平凡函数,并且如果x是object,ex是表达式的潜在结果集合的元素e,其中左值到右值的转换(4.1)应用于e或者e是丢弃值表达式(第5节).

这看起来很复杂,并且在早期版本的标准中更简单.但是,它大致表示当表达式"立即"访问变量值时,某个表达式不会使用该变量,并且此访问会产生常量表达式.迈尔斯"取其地址"的例子只是众多因素之一.

对于某些类A及其静态数据成员i,

class A {
    static const int i = 57; // Declaration, not definition
};

const int A::i; // Definition in namespace scope. Not required per se.
Run Code Online (Sandbox Code Playgroud)


hac*_*cks 2

在此声明:

在类接口中初始化的静态const整型数据成员不是可寻址变量。它们只是其相关值的象征性名称。由于它们不是变量,因此无法确定它们的地址。注意,这不是编译问题,而是链接问题。在类接口中初始化的静态const变量不作为可寻址实体存在。

这里的“可寻址实体”指的是静态const数据类型的“实例”。没有实例,没有地址,即它只是一个声明。
请注意,在源文件中显式定义的静态变量可以正确链接。

class X
{
    public:
        static int const s_x = 34;
        static int const s_y;
};

int const X::s_y = 12;

int main()
{
    int const *ip = &X::s_x;    // compiles, but fails to link
    ip = &X::s_y;               // compiles and links correctly
} 
Run Code Online (Sandbox Code Playgroud)

...如果您确实获取类常量的地址,或者如果您的 .. 是上面引用的段落的一部分?

意味着如果这样的成员是 odr 使用的,则仍然需要命名空间范围内的定义,但它不应该具有初始值设定项。

struct X {
    const static int n = 1;
};
const int* p = &X::n; // X::n is odr-used
const int X::n;       // ... so a definition is necessary
Run Code Online (Sandbox Code Playgroud)

  • 那句话是不正确的。您可以定义一个 const 整型数据成员并获取其地址。 (2认同)