【问题标题】:Declaring a variable size array as a class/template class member variable将可变大小数组声明为类/模板类成员变量
【发布时间】:2020-04-01 12:51:23
【问题描述】:

我正在尝试用 C++ 编写一个包含二维数组成员变量的类。这个类的重点是使用这个数组来表示一个模拟的物理模型,我打算把我想在数组上执行的各种动作写成成员函数。

我的问题是尝试在不进行硬编码的情况下初始化类中的数组-理想情况下,我想编写整个程序,以便用户可以在运行时输入数组的维度,这可以然后在类的重载构造函数中使用。即这样的事情:


class Lattice{
public:
    //Overload constructor
    Lattice(int);
private:
    //variables:
    int DimensionSize;
    int lattice[DimensionSize][DimensionSize];
}

Lattice::Lattice(int N){
    DimensionSize = N;
    lattice = new int[DimensionSize][DimensionSize];
}

我可以看到上面的代码显然不起作用,因为变量“DimensionSize”在运行时未指定,这意味着二维数组“lattice”所需的内存量是未知的。

我一直在这个论坛上寻找答案,但似乎没有任何对我的问题有直接帮助的东西,而且已经提出的任何其他问题似乎都很老了。如果有人能指出我的解决方案,或者让我知道我想要的是否可能,我将不胜感激 - 我想知道使用向量而不是数组是否可能是一个解决方案?

更新:

我能够通过使用模板类产生我想要的行为:

template <int N>
class Lattice
{
public:
    //Constructor
    Lattice();
    ~ some other functions ~

private:
    float lattice[N][N];
};

template <int N>
Lattice<N>::Lattice() {
    double rando;
//    Initialise the array to a random state.
    for(int i = 0; i < N; i++) {
        for(int j = 0; j < N; j++){
            rando = (double)rand() / ((double)RAND_MAX + 1);
            if( rando <= 0.5 ){
                lattice[i][j] = -1.0;
            }
            else if( rando >= 0.5 ){
                lattice[i][j] = 1.0;
            }
        }
    }
}

我可以看到使用向量而不是数组是可能的,所以我现在的问题是使用上述模板是否有任何主要缺点?我可以看到类声明和定义现在必须包含在同一个头文件中,如该线程Why can templates only be implemented in the header file? 中所述,但除了这种不便之外,是否还有其他问题?

【问题讨论】:

  • 如果您需要使用动态分配,那么 int lattice[DimensionSize][DimensionSize]; 必须是 int** lattice; - 尽管使用像 std::vector&lt;std::vector&lt;int&gt;&gt; lattice; 这样的适当容器会更好
  • std::vector 是这项工作的工具,尽管不要使用 2d 工具。有关如何使用单个向量假装具有多维向量的信息,请参阅此:stackoverflow.com/questions/43358369/…
  • 是的。数组的大小应在编译时确定。你需要的正是std::vector
  • 对于模板,size_tint 更合适。

标签: c++ arrays class templates vector


【解决方案1】:

如 cmets 中所述,如果您想声明一个二维数组,然后使用 new 分配它,请像这样声明它:int** lattice。 另外,我建议将其声明为单个数组(或向量),以便所有元素在内存中都是连续的,然后使用 x、y 和 DimensionSize 计算元素位置:

class Lattice{
public:
    //Overload constructor
    Lattice(int);
    //access-method
    int getElement(int x, int y)
private:
    //variables:
    int DimensionSize;
    //simple pointer
    int* lattice;
}

Lattice::Lattice(int N){
    DimensionSize = N;
    lattice = new int[DimensionSize*DimensionSize];
}

int Lattice::getElement(int x, int y)
{
    \\calculate the element-position from x and y using DimensionSize
    return lattice[x + y*DimensionSize]; 
}

由于lattice 是私有成员,因此无论如何您都必须定义访问方法,并且将所有元素连续存储在内存中可以大大加快访问速度。

编辑:这是带有显式二维数组的代码:

class Lattice{
public:
    //Overload constructor
    Lattice(int);
    //access-method
    int getElement(int x, int y)
private:
    //variables:
    int DimensionSize;
    //simple pointer
    int** lattice;
}

Lattice::Lattice(int N){
    DimensionSize = N;
    lattice = new int[DimensionSize][DimensionSize];
}

int Lattice::getElement(int x, int y)
{
    return lattice[x][y]; 
}

【讨论】:

  • 感谢您的回复-但为什么lattice = new int[DimensionSize*DimensionSize]; 行不是:lattice = new int[DimensionSize][DimensionSize]; 作为二维数组通常已初始化?
  • 正如我所说,将其声明为单个数组将导致所有元素在内存中彼此相邻,并允许您仅通过一种间接方式访问它们,从而使访问速度更快。但是,如果您更清楚,请随意将其初始化为 lattice = new int[DimensionSize][DimensionSize];
  • 啊好吧,我明白你的意思了——我认为int[][] 声明对我来说是必要的,因为位置 (i,j) 对于计算依赖于形容词元素的各种参数很重要(i + 1, j + 1) 等等。不过,访问速度对我来说很重要——你知道使用 1d 数组而不是 2d 数组的速度提升有多重要吗? (似乎可以使用一维数组,但它需要大量额外的代码......)
猜你喜欢
  • 1970-01-01
  • 2019-01-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-18
  • 1970-01-01
相关资源
最近更新 更多