C++变量数组作为类成员

5

我有一个如下定义的小型C++程序:

class Test
{
   public:
   int a;
   int b[a];
};

编译时出现错误:
testClass.C:7:5: error: invalid use of non-static data member ‘Test::a’
testClass.C:8:7: error: from this location
testClass.C:8:8: error: array bound is not an integer constant before ‘]’ token

我该如何了解错误信息的含义以及如何修复它?


7
数组必须有一个固定的大小。你不能根据可变的变量分配数组的大小。 - Linger
类可以转换为模板。template <int sz> 类 Test { public: int b[sz]; }; - pmw1234
3个回答

11

在编译时,您不能使用大小未定义的数组。有两种方法:将a定义为static const int a = 100;并忘记动态大小,或者使用std::vector,它比手动内存管理更安全:

class Test
{
public:
  Test(int Num)
    : a(Num)
    , b(Num) // Here Num items are allocated
  {
  }
  int a;
  std::vector<int> b;
};

1
好的,实际上我们并不需要 a。我们可以摆脱这个成员变量,直接使用 b.size() - demi
确实,坦率地说,这是我第一次看到向量以这种方式初始化,我喜欢stackoverflow,它教给我们很多东西! - Ahmed Jolani

6
除非您动态分配它们(例如使用new[]),否则C ++中的数组必须具有编译时常量作为大小。而Test::a不是编译时常量,它是一个成员变量。

5
让我们详细了解一下这背后的原因。首先,当您最初声明一个类时,任何成员变量都没有分配任何内存,因此公共或私有方法没有值。那是给您的一个快速提示,现在来看看您的问题:
您不能在类外部执行此操作,因为任何数组大小都应该在编译之前知道,因为任何静态声明的数组都驻留在函数的堆栈帧中,编译器需要准确地知道要分配多少内存。程序员调整的唯一内存段是堆。因此,每当您想要具有动态分配的数组大小时,您需要声明它驻留在堆中,并且可以通过以下方式完成:
int a;
cin >> a;
int * b = new int[a];

这是声明一个大小未知的数组(在运行时确定大小)的正确方法,要将其与您的类集成,以下是如何实现的。请注意,任何类的私有或公共属性都没有内存 - 它们只是声明,不应该在成员方法或类外部初始化 - 这是因为它们是公共的,就像您的情况一样 - 当然,在声明类的实例(例如Test t)之后。无论如何,以下是在类中的实现方式:

class Test
{
public:
int a;
int * b;
Test(int Ia=1) {
    a = Ia;
    b = new int[a];
}
~Test() {
    delete[] b;
}
};

请参考C++中delete和delete[]运算符的区别,了解为什么在析构函数中应该使用delete[]而不是delete

不要忘记三法则。那么std::vector呢? - Nicol Bolas
也就是说,不要动态分配数组,而是使用std::vector。这样,您就不需要析构函数或各种复制赋值运算符。 - Nicol Bolas
2
类不安全复制和赋值。 - demi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接