作者:DYongLi | 来源:互联网 | 2023-05-18 16:11
Myknowledgeofthestackascomparedwiththeheapisveryrudimentary,butwhenitcomestoarrays
My knowledge of the stack as compared with the heap is very rudimentary, but when it comes to arrays, from what I know something like this is created on the stack
与堆相比,我对堆栈的了解非常简陋,但是当涉及到数组时,从我所知道的内容就是在堆栈上创建的
float x[100];
whereas something like this is created on the heap
而这样的东西是在堆上创建的
float* x = new float[100];
But what happens if I create a template array class, and pass it in a "stack" array type (like float[100]
)? Example:
但是如果我创建一个模板数组类并将其传递给“堆栈”数组类型(如float [100])会发生什么?例:
#include
using namespace std;
template
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* array = new Array(m);
for (int i = 0; i data[i][j] = i * j;
cout <data[10][9] <
What exactly is going on here? Is this memory created on the stack, or on the heap? My guess is the heap, but how does this work? Does the compiler allocate one large block of memory, and then store pointers that index into it every n
elements? Or does it allocate many smaller blocks of memory (not necessarily contiguous), and store pointers to each block?
到底发生了什么?这个内存是在堆栈上还是在堆上创建的?我的猜测是堆,但这是如何工作的?编译器是否分配一个大的内存块,然后存储每n个元素索引到它的指针?或者它是否分配了许多较小的内存块(不一定是连续的),并存储指向每个块的指针?
Furthermore, I can't seem to do this without the aid of a template. Specifically, this code does not compile:
此外,没有模板的帮助,我似乎无法做到这一点。具体来说,此代码无法编译:
int m = 1000;
const int n = 100;
(float[n])* array = new (float[n])[m];
What is going on here?
这里发生了什么?
EDIT:
Thanks for the syntax tips, everyone. What I was really interested in is what happens in the block
感谢大家的语法提示。我真正感兴趣的是块中发生的事情
int m = 1000;
const int n = 100;
float (*array)[n] = new float[m][n];
but I didn't know how to write it without the use of templates. One thing I was really interested in is if the compiler allocates this as one large block on the heap, how can you use the syntax array[i][j]
to access a particular element without storing pointers to every n-th element? Then I realized that since n
is constant, sizeof(float[n])
is fixed, so when you make the array, the compiler is allocating an array of m
elements where each element is a float[n]
, which in my case is 100 * 4 = 400
bytes. Now it all makes sense. Thanks!
但我不知道如何在不使用模板的情况下编写它。我真正感兴趣的一件事是,如果编译器将其分配为堆上的一个大块,那么如何使用语法数组[i] [j]访问特定元素而不存储指向每个第n个元素的指针?然后我意识到由于n是常量,sizeof(float [n])是固定的,所以当你创建数组时,编译器会分配一个m元素的数组,其中每个元素都是一个float [n],在我的例子中是100 * 4 = 400字节。现在一切都有道理。谢谢!
4 个解决方案
3
Array* array = new Array(m);
What is going on here is two heap allocations. The Array
object will be allocated on the heap because you used new
to create it. The new-expression calls the Array
constructor, which again uses new
to allocate the array data
; therefore data
is also allocated on the heap.
这里发生的是两个堆分配。 Array对象将在堆上分配,因为您使用new来创建它。 new-expression调用Array构造函数,它再次使用new来分配数组数据;因此,数据也在堆上分配。
It is better to do this:
最好这样做:
Array array(m);
This allocates array
on the stack (so it will automatically be destroyed at the end of the block). However, while the array
object itself is on the stack, the data is still stored on the heap because it's allocated on the heap in the Array
constructor. This is similar to what happens when you have a std::vector
or std::string
local variable.
这会在堆栈上分配数组(因此它会在块的末尾自动销毁)。但是,虽然数组对象本身位于堆栈上,但数据仍然存储在堆上,因为它是在Array构造函数的堆上分配的。这类似于当你有一个std :: vector或std :: string局部变量时会发生的事情。
Furthermore, I can't seem to do this without the aid of a template. Specifically, this code does not compile:
此外,没有模板的帮助,我似乎无法做到这一点。具体来说,此代码无法编译:
This is just because your syntax is wrong. The correct syntax is:
这只是因为你的语法错误。正确的语法是:
float (*array)[n] = new float[m][n];
The left-hand side shows the correct way to declare a pointer to an array. For the right-hand side, you want an array of m
float[n]
s. This is denoted float[m][n]
; the [m]
doesn't go at the end.
左侧显示了声明指向数组的指针的正确方法。对于右侧,您需要一个m float [n]的数组。这表示为float [m] [n]; [m]最后没有结束。
0
In the line
在线
Array* array = new Array(m);
An instance of Array
is allocated on the heap. You already understood that, given your first statement about allocations in general.
在堆上分配Array
的实例。你已经明白了,一般来说你的第一个关于分配的陈述。
Perhaps the confusing part is the use of float[n]
as a template parameter?
也许令人困惑的部分是使用float [n]作为模板参数?
The template parameter T
, as denoted by the keyword class
in your definition of Array
, represents a type. It isn't in itself related to any form of allocation.
模板参数T(由Array定义中的关键字class表示)表示一种类型。它本身与任何形式的分配无关。
As a demonstration of this, let's write a simple template which doesn't make any use of its parameter:
作为对此的演示,让我们编写一个简单的模板,它不会使用它的参数:
#include
using namespace std;
template
class A {
};
int main(){
A a1;
A a2;
float f[100];
assert(sizeof(a1) == sizeof(a2));
cout <<"a1 : " <
Output:
a1 : 1
f : 400
So float[n]
here is indeed a type(1).
所以float [n]在这里确实是一个类型(1)。
On the other end, when you use the keyword new
, you know that something is being allocated on the heap. So as I said, the array
variable will point to a memory chunk in the heap. Furthermore the template itself contains a heap allocation (again, keyword new
).
另一方面,当您使用关键字new时,您知道正在堆上分配某些内容。正如我所说,数组变量将指向堆中的内存块。此外,模板本身包含堆分配(同样,关键字new)。
Finally, I would like to nuance the basic premise that new
indicates a heap allocation. While by default it is the case, when used in placement mode, the actual allocation could very well be on the stack.
最后,我想细化新的表明堆分配的基本前提。虽然默认情况下是这样,但在放置模式下使用时,实际的分配很可能在堆栈上。
(1) Note that C++ accepts it as such because n
is declared as a constant, and thus the resulting type may be evaluated at compilation time. Remove the const
trait of the definition of n
, and the compiler will complain.
(1)注意C ++接受它是因为n被声明为常量,因此可以在编译时评估结果类型。删除n定义的const特性,编译器会抱怨。