C++ 可变长度数组在主函数中编译,但不在类声明中编译?

C++ 可变长度数组在主函数中编译,但不在类声明中编译?,c++,arrays,class,c++11,g++,C++,Arrays,Class,C++11,G++,在用户报告中,他的g++版本编译了VLAs,以及在中。在我的编译器上,这也是可行的(有那个扩展),但是如果我想声明这样一个数组作为类成员,比如position和velocity class PSO { private: static double * data; static int len; static int dim; double position [dim]; double velocity [di

在用户报告中,他的g++版本编译了VLAs,以及在中。在我的编译器上,这也是可行的(有那个扩展),但是如果我想声明这样一个数组作为类成员,比如
position
velocity

class PSO
{
    private:
        static double * data;
        static int len;
        static int dim;
        double position [dim];
        double velocity [dim];

        double get_min();
        double get_max();
        void copy_data(double data *);

//...
它不编译。这是什么原因?为什么编译器扩展在
main
函数中允许VLA,而在类成员的声明中不允许VLA

附录

我使用的是GCC4.8.2

编辑

我知道我应该使用
std::vector
或指针,但我想知道为什么它会在主函数中编译,而不是在类声明中编译

编辑2

明确地说,这是编译(在我的例子中)


这与我展示的其他问题不完全相同,因为在数组声明之前我没有
std::cin>>size
语句。其他人的编译器中有这种(怪癖)吗?

这绝对是个猜测,我最近主要是用C编程的。可能是因为类和结构需要有一个以字节为单位的标准大小,这样它们就可以以固定的间隔线性地存储在内存中,同时也可以被使用sizeof的代码遍历。如果允许VLA,那么一个对象可能有一个16字节的数组,另一个对象可能有一个16000字节的数组。那么编译器是如何编写代码来遍历不同长度的对象的呢?我猜:这只是一个错误,并不麻烦


我相信你可以通过使用malloc和指针来解决这个问题。

这绝对是一个猜测,我最近主要是用C编程的。可能是因为类和结构需要有一个以字节为单位的标准大小,这样它们就可以以固定的间隔线性地存储在内存中,同时也可以被使用sizeof的代码遍历。如果允许VLA,那么一个对象可能有一个16字节的数组,另一个对象可能有一个16000字节的数组。那么编译器是如何编写代码来遍历不同长度的对象的呢?我猜:这只是一个错误,并不麻烦


我相信您可以通过使用malloc和指针来解决这个问题。

当您在运行时之前不知道数组的长度时,应该使用指针。在您的示例中,这将按照以下方式进行:

class PSO
{
    private:
        static double * data;
        static int len;
        static int dim;
        double* position;
        double* velocity;

        double get_min();
        double get_max();
        void copy_data(double data *);

    //...
}
然后在代码中的某个地方实例化指针(例如
PSO
的构造函数),如下所示:

position = new double[dim];
velocity = new double[dim];
struct MyOtherObject {
    int dim;
    int x[dim];
    int y[dim];
};
请记住,您不能在类定义中定义变量,只能声明它们


<>请不要忘记,因为你在C++中编写,你也可以访问其他结构,比如“代码>矢量< /Cord>”,它可以在动态大小的数组中保存变量。

< P>当你不知道数组的长度,直到运行时,你应该使用指针。在您的示例中,这将按照以下方式进行:

class PSO
{
    private:
        static double * data;
        static int len;
        static int dim;
        double* position;
        double* velocity;

        double get_min();
        double get_max();
        void copy_data(double data *);

    //...
}
然后在代码中的某个地方实例化指针(例如
PSO
的构造函数),如下所示:

position = new double[dim];
velocity = new double[dim];
struct MyOtherObject {
    int dim;
    int x[dim];
    int y[dim];
};
请记住,您不能在类定义中定义变量,只能声明它们


<>请不要忘记,因为你在C++中编写,你也可以访问其他结构,比如代码>矢量< /C> >,它可以在动态大小的数组中保存变量。

< P>使用“代码> ALOLACA</代码> /只修改堆栈指针,很容易创建本地VLA。在一个类型中支持它有很多挑战(打破偏移量/成员指针等)。将其作为对象的一部分进行分配将使其大小动态变化,从而使赋值和指针运算变得更加复杂。因为我们可以使用指向对象外部数据的指针,所以似乎不值得为类型支持它。

使用
alloca
/只需修改堆栈指针,就可以很容易地创建本地VLA。在一个类型中支持它有很多挑战(打破偏移量/成员指针等)。将其作为对象的一部分进行分配将使其大小动态变化,从而使赋值和指针运算变得更加复杂。因为我们可以使用指向对象外部数据的指针,所以似乎不值得在类型上支持它。

所以,让我们先澄清一下。C++中的可变长度数组是编译器扩展。这不是直接通过C++标准支持的。 这里讨论的是两种不同的VLA。堆栈分配和最后一个结构成员分配。让我们一次处理一个

堆栈分配 在这里,我们只是简单地讨论如下内容:

int main() {
    int length = 12;
    float array[length];
}
这相当简单。我们有一个指向当前使用的堆栈空间末尾的指针,当我们到达
数组
声明时,我们扩展了该指针

结构分配 这更复杂。支持的普通编译器扩展允许最后一个成员为可变长度数组。但我们只能通过一种方式做到这一点:

struct MyObject {
    int x;
    float y;
    double z[]; // Note that we didn't give this any length!
};
现在。通过
sizeof()
此对象的大小是多少?可能是
8
。此大小不为数组
z
分配空间。它假定长度为0。那么我们能用这个做什么呢

struct MyObject *object = malloc(sizeof(MyObject) + 8*sizeof(double));
这允许我们通过
对象->z
数组访问8个双精度

现在,为什么我们不能做其他事情呢? 如果有足够的编译器扩展,我们可以做更多的事情。但问题是,一般来说,我们最多只想做一个指针加上一对(但数量固定)的计算偏移量到系统中的每个变量。这两个扩展并没有打破这种愿望

你建议的代码怎么样? 允许这样的事情:

position = new double[dim];
velocity = new double[dim];
struct MyOtherObject {
    int dim;
    int x[dim];
    int y[dim];
};
我可以工作。但是,这是一个更复杂的扩展。而且不包括在内。它有一些问题,比如在分配发生后有能力更改
dim
。但最终,这些问题是可以解决的

但是那条鳕鱼