数组作为模板参数:堆栈还是堆?

hun*_*nse 6 c++ arrays templates heap-memory stack-memory

与堆相比,我对堆栈的了解非常简陋,但是当涉及到数组时,从我所知道的内容就是在堆栈上创建的

float x[100];
Run Code Online (Sandbox Code Playgroud)

而这样的东西是在堆上创建的

float* x = new float[100];
Run Code Online (Sandbox Code Playgroud)

但是如果我创建一个模板数组类,并以"堆栈"数组类型(如float[100])传递它会发生什么?例:

#include <iostream>

using namespace std;

template <class T>
class Array {
public:
    int size;
    T* data;

    Array(int size_) : size(size_) {
        data = new T[size];
    }

    ~Array() {
        delete [] data;
    }
};

int main() {
    int m = 1000000;
    const int n = 100;
    Array<float[n]>* array = new Array<float[n]>(m);

    for (int i = 0; i < m; i++)
        for (int j = 0; j < n; j++)
            array->data[i][j] = i * j;

    cout << array->data[10][9] << endl;
    delete array;
}
Run Code Online (Sandbox Code Playgroud)

到底发生了什么?这个内存是在堆栈上还是在堆上创建的?我的猜测是堆,但这是如何工作的?编译器是否分配了一个大的内存块,然后存储每个n元素都会为其编入索引的指针?或者它是否分配了许多较小的内存块(不一定是连续的),并存储指向每个块的指针?

此外,没有模板的帮助,我似乎无法做到这一点.具体来说,此代码无法编译:

int m = 1000;
const int n = 100;
(float[n])* array = new (float[n])[m];
Run Code Online (Sandbox Code Playgroud)

这里发生了什么?

编辑:

感谢大家的语法提示.我真正感兴趣的是块中发生的事情

int m = 1000;
const int n = 100;
float (*array)[n] = new float[m][n];
Run Code Online (Sandbox Code Playgroud)

但我不知道如何在不使用模板的情况下编写它.我真正感兴趣的一件事是,如果编译器将其分配为堆上的一个大块,那么如何在array[i][j]不存储指向每个第n个元素的指针的情况下使用语法来访问特定元素?然后我意识到因为n是常量,sizeof(float[n])所以是固定的,所以当你创建数组时,编译器会分配一个m元素数组,其中每个元素都是a float[n],在我的例子中是100 * 4 = 400字节.现在一切都有道理.谢谢!

eca*_*mur 2

您已经向后写入了数组范围。这有效:

  int m = 1000;
  const int n = 100;
  float (*array)[n] = new float[m][n];
  delete[] array;
Run Code Online (Sandbox Code Playgroud)

如果您想让数组范围保持相同的顺序,您可以使用类型别名或适当的模板:

  using A = float[n];
  A* array = new A[m];
Run Code Online (Sandbox Code Playgroud)

或者

// at file scope
template<typename T, unsigned N> using add_extent = T[N];
// ...
  add_extent<float, n>* array = new add_extent<float, n>[m];
Run Code Online (Sandbox Code Playgroud)

无论是在堆栈还是堆上的多维数组都被分配为单个m*n元素块。当您对指向数组类型的指针(如float (*array)[n])进行索引时,指针会n按照数组类型的跨度一次递增元素。