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

我的堆与堆相比的知识是非常基本的,但是当涉及到数组时,从我知道的东西这样的东西在堆栈上创建

float x[100];

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

float* x = new float[100];

但是,如果我创建一个模板数组类,并将其传入“堆栈”数组类型(如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;
}

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

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

int m = 1000;
const int n = 100;
(float[n])* array = new (float[n])[m];

这里发生了什么?

编辑:

感谢大家的语法提示。 我真正感兴趣的是这个街区发生了什么

int m = 1000;
const int n = 100;
float (*array)[n] = new float[m][n];

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


你已经向后写了你的数组范围。 这工作:

  int m = 1000;
  const int n = 100;
  float (*array)[n] = new float[m][n];
  delete[] array;

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

  using A = float[n];
  A* array = new A[m];

要么

// at file scope
template<typename T, unsigned N> using add_extent = T[N];
// ...
  add_extent<float, n>* array = new add_extent<float, n>[m];

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


Array<float[n]>* array = new Array<float[n]>(m);

这里发生的是两堆分配。 Array对象将在堆上分配,因为您使用new来创建它。 new-expression调用Array构造函数,它再次使用new来分配数组data ; 因此data也被分配到堆上。

这样做更好:

Array<float[n]> array(m);

这会在堆栈中分配array (所以它会在块的末尾自动销毁)。 但是,当array对象本身位于堆栈上时,数据仍然存储在堆中,因为它在Array构造函数的堆中分配。 这与当你有一个std::vectorstd::string局部变量时发生的情况类似。

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

这只是因为你的语法错了。 正确的语法是:

float (*array)[n] = new float[m][n];

左侧显示了声明指向数组的指针的正确方法。 对于右侧,你需要一个m float[n] s的数组。 这被表示为float[m][n] ; [m]不会结束。


所有的记忆都在堆上。 编译器为阵列分配一个巨大的内存块,并设置索引以便可访问。

另外,如果有人拷贝或分配你的Array类,你会泄漏内存和/或双重删除。

链接地址: http://www.djcxy.com/p/82733.html

上一篇: Array as template parameter: stack or heap?

下一篇: Multilevel Paging Operating System