【问题标题】:Why does this variable need to be static?为什么这个变量需要是静态的?
【发布时间】:2014-10-28 21:26:41
【问题描述】:
class armon
{
    static const int maxSize=10;    

    int array[maxSize];

    int count=0;

    int* topOfStack=array;
}

为什么maxSize 必须是static 才能在数组中使用?

【问题讨论】:

    标签: c++ arrays static member


    【解决方案1】:

    必须是静态的,但它必须是常量表达式

    C++ 标准§ 8.3.4 [dcl.array](强调我的):

    如果存在常量表达式 (5.19),它应该是转换后的std::size_t 类型的常量表达式,并且它的值应该大于零


    也就是说,以下也是有效的:

    constexpr std::size_t Size()  { return 10; }; 
    
    struct Y
    {
        int array[Size()];
    };
    

    注意:

    由于编译器需要知道类的大小,你不能这样做:

    struct Y
    {
        const int size = 10;
        int array[size];
    };
    

    可能使Y 的不同实例具有不同的大小。

    还要注意,在这种情况下,int array[size] 不是一个常量表达式,因为它使用了this,请参阅 C++ 标准部分 § 5.19 [expr.const]:

    条件表达式 e 是核心常量表达式,除非根据抽象机 (1.9) 的规则对 e 的求值将求值以下表达式之一:

    this (5.1.1),除了在作为 e 的一部分计算的 constexpr 函数或 constexpr 构造函数中;

    size的评价真的是this->size

    【讨论】:

    • 这是因为编译器能够在编译期间保留内存。很好的解释here
    • 你还需要解释一下为什么const int maxSize = 10;不考虑给出常量表达式,而static const int maxSize = 10
    • @MattMcNabb 当然,添加注释
    • 下一个问题,鉴于实际上没有Y() : size(5) {},为什么在这种情况下size 不应该是一个常量表达式?
    • @MattMcNabb 查看我的第二次编辑,它不是一个常量表达式(第 5.19 节)
    【解决方案2】:

    这个问题有两个方面

    方面 1

    C++ 数组是固定大小的,在编译时需要知道它的大小。如果需要在运行时延迟决策,则数组表达式会变得不正确。

    方面2

    将成员变量声明为非静态使其成为实例变量,其值仅在对象被实例化后才存在,该对象在运行时完成。静态变量是类变量,其值可以在编译时确定。

    你的具体例子变成了经典的鸡蛋悖论。

    class armon
    {
        static const int maxSize=10;    
    
        int array[maxSize];
    
    }
    
    • 为了实例化你的类armon,你需要知道它的大小。
    • 为了知道它的大小,你需要知道单个成员的大小。在您的特定情况下,您需要知道数组的大小。
    • 为了知道数组的大小,需要知道因变量maxSize的值。
    • 为了访问因变量 maxSize,您需要实例化类 armon
    • 为了实例化你的类armon,你需要知道它的大小。

    因此,您的数组大小因变量应该是一个常量表达式,在您的特定情况下应该是一个静态变量,

    【讨论】:

      【解决方案3】:

      它不必是静态的,它必须是恒定的。

      当您在类中声明一个常量时,您将为该类的每个实例创建一个常量

      此外,如果您的maxSize 只是const,则您必须在构造函数初始化程序列表中对其进行初始化,因为const maxSize 被视为您无法更改其值的变量。

      类内const 关键字的意思是“这是这个对象的空洞生命周期内的一个常数”。 同一类的不同对象可以对该常量具有不同的值。

      但是当它是一个静态常量时,类的所有实例只有一个常量。这意味着您必须在定义它的同一行上初始化常量值。

      【讨论】:

      • "如果你的 maxSize 只是 const 你必须在构造函数初始化列表中初始化它"是错误的!它也可以是一个不必在初始化列表中初始化的作用域变量。 “在类中的 const 关键字意味着“这是该对象的空洞生命周期内的常量””也是错误的。这只是对程序员的“提示”。想想const_cast<>
      • @lifeOfPI:这不仅仅是一个提示。您不能抛弃 const_ness 并以非常量的方式使用该对象。那将是未定义的行为,并且可能以非常意想不到的方式中断。它中断的一种预期方式是编译器可能已经创建了一个常量的多个副本,而您只需更改一个。
      • 您不必在构造函数初始化程序列表中对其进行初始化,例如int count = 0; 在 OP 的代码中。
      • @MSalters:IMO 你说对了一部分,it is 1 of 3 scenarios。所以const 不保证永远不会改变。
      • lifeOfPi const 对象可能不会被您的代码修改,故事结束。
      猜你喜欢
      • 1970-01-01
      • 2023-04-11
      • 2012-09-08
      • 1970-01-01
      • 2020-10-22
      相关资源
      最近更新 更多