C++头文件中的数组声明

12
我想知道是否可以在类的私有成员中声明一个数组(此时大小未知),并在类的构造函数中设置数组的大小。例如:

我想知道是否可以在类的私有成员中声明一个数组(此时大小未知),并在类的构造函数中设置数组的大小。例如:

class Test {
int a[];
public:
Test(int size);
};

Test::Test(int size) {
a[size];   // this is wrong, but what can i do here?
}

这是否可行,还是我应该使用动态数组?谢谢!

7个回答

17

简短回答:不行(数组的大小只在编译时定义)
长回答:

您可以使用向量来实现相同的结果:

class Test
{
    std::vector<int> a;
    public:
        Test(std::size_t size):
            a(size)
        {}
};

我希望人们在标记答案时能添加注释。至少你回到了0。 - JaredPar
2
黑子们喜欢匿名地恶意攻击。讨厌那些恶意攻击者!我给你一个赞。 - John Dibling
+1 对于一个好的实用答案,如果有人对其有问题,请解释原因(这样我们就可以向您展示Martin是正确的) - orip
+1 给你,std::vector<> 很棒。一个小问题是在构造函数中使用 size_t 而不是 int。 - Andreas Magnusson
@Andreas Magnusson:我们发现了。已更新。但是如果您的向量大小超出了有符号整数的范围,我认为您还有其他问题。 - Martin York

16

不可能做到这一点。头文件中的数组声明必须具有常量大小值。否则,像 "sizeof" 这样的构造就无法正常工作。您需要将数组声明为指针类型,并在构造函数中使用 new[]。例子。

class Test { 
    int *a;
public:
    Test(int size) {
       a = new int[size];
    }
    ~Test() { delete [] a; }
private:
    Test(const Test& other);
    Test& operator=(const Test& other);
};

需要添加复制构造函数和赋值运算符,并调用正确版本的delete。或者使用一个向量。 - Martin York
糟糕,我通常会因为同样的问题指责别人...很快就会修复。 - JaredPar
双倍错误 ;( 今天是逻辑星期五 - JaredPar
1
绝对同意向量更好。原始示例未使用STL,因此我决定在没有STL的情况下回答。STL使C++变得更好。我发现越来越难将两者分开。 - JaredPar
你很可能还需要一个变量来存储a的大小。 - ypnos

5

正如其他答案所指出的那样,数组的大小在编译时是固定的。但是,通过使用模板,您可以在编译时将大小参数化:

template <int N> class Test {
    int a[N];
public:
    Test() { }
};

Test<5> test;
Test<40> biggertest;

这种技术不允许您在运行时计算大小(与动态std::vector解决方案不同),但根据您的需求,这可能已经足够了。


可以运行,但是每个Test的版本现在都是不同的类。因此没有隐式友元(因此不能访问复制等)。 - Martin York
无论如何,您也不能将Test<2>复制到Test<1>中 - 它不适合。此外,没有多态性 - Test<1>和Test<2>是不兼容的类型,因此处理它们的每个函数也必须是模板化的。 - Steve Jessop
没关系。他仍然可以为operator=和cctor创建模板。 - Johannes Schaub - litb
@Greg:有趣的提示。这又是一个泛型不等于模板的原因。或者说,是泛型小于模板?;-) - James Schek

3

首先,通常最好在构造函数的初始化列表中初始化事物,而不是在构造函数体中。

如果您知道编译时的限制,只能使用预定义的边界来初始化数组。在这种情况下,您需要动态分配空间。

您必须记住,在对象被销毁时具有删除数组的析构函数,否则会导致内存泄漏。


2

可以参考Martin的解决方案(使用std::vector),并记住,即使需要将缓冲区传递给C API,std::vector也可以通过传递&vec[0]来实现:

std::vector<char> vec(10);
memset(&vec[0], 0, vec.size());

保证代码可以运行,但前提是向量不为空(C++的怪癖,唉)。


我经常使用&vec[0]技巧,尽管在这种情况下memset()是多余的,因为vec已经被初始化为全零。 - Andreas Magnusson

0
不,这是不可能的。您应该使用动态数组,例如std::vector。C99仅允许结构体作为最后一个成员具有无大小数组,但即使这样,您仍然必须手动分配内存,例如使用malloc()

0
你所说的是不可能的。类的大小总是固定的。你可以让你的类使用指向动态分配数组的指针,或者你可以使用std::vector。

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