如果您使用 value-types 作为数组元素,那么数组使用的存储空间更少。
我以 C 为例:
1。值数组:
struct Value {
int x;
}
sizeof(Value) == 4 bytes (assuming zero overhead)
struct Value staticArray[10]; // will consume 10 * 4 == 40 bytes
2。如果是指针数组,那么:
struct Value* staticArrayOfPointers[10];
for( size_t i = 0; i < sizeof(staticArrayOfPointers); i++ ) {
staticArrayOfPointers[i] = calloc( sizeof(struct Value), 1 );
}
-
staticArrayOfPointers 本身无论如何都会消耗 40 个字节,因为指针是 4 个字节长
- 但它还需要为每个索引分别分配每个元素,因此还有 40 个字节。
- 总共 80 个字节。
3。如果是使用内联值的链表,则使用堆:
struct Node {
struct Value value; // stored inline, as a value, in the node, not elsewhere in memory
Node* next;
}
sizeof(struct Node) == 8 bytes (assuming zero overhead and alignment, and 4-byte pointers)
struct Node* head = calloc( sizeof(struct Node), 1 ); // calloc zeroes memory
struct Node* current = head;
for( size_t i = 0; i < 10; i++ ) {
current->next = calloc( sizeof(struct Node), 1 );
current = current->next;
}
现在,链表在内存中至少有 10 * 8 (80) 个字节,并且也可能是碎片化的,因为每个节点可能存在于内存中的不同位置。
4。如果它是使用指向值的指针的链表(也使用堆):
struct Node2 {
struct Value* valuePtr;
Node* next;
}
sizeof(struct Node2) == 8 (as a pointer is also 4 bytes), but then add another 4 bytes for the `Value` instance located elsewhere:
struct Node2* head = calloc( sizeof(struct Node2), 1 ); // calloc zeroes memory
head->valuePtr = calloc( sizeof(struct Value), 1 );
struct Node2* current = head;
for( size_t i = 0; i < 10; i++ ) {
current->next = calloc( sizeof(struct Node2), 1 );
current->valuePtr = calloc( sizeof(struct Value), 1 );
current = current->next;
}
此版本现在将消耗 10 * ( 8 + 4 ) == 120 字节,但随着分配的增加,碎片的可能性也增加了。
总结:
- 值数组:
n * sizeof(Element)
- 指向值的指针数组:
n * ( sizeof(Element*) + sizeof(Element) )
- 值的链接列表:
n * ( sizeof(Element) + sizeof(Node*) )
- 指向值的指针的链接列表:
n * ( sizeof(Element*) + sizeof(Element) + sizeof(Node*) )
注意事项:
- 这取决于语言。如果它是一种像 C 或 C++ 这样可以让您完全控制内存的语言,那么您可以使用上述任何一种方法。
- 如果是Java,那么只有原始类型(
int,double,但不是string)是值类型,所有其他类型都是“引用类型”并在内部使用指针,但因为它是一个GC环境中您不会遭受致命的内存碎片...希望如此。
- 如果是 C# 或 Swift,您可以使用值类型(
struct 与 class),那么您可以使用所有 4 个选项,但指针本身不会暴露。
- JavaScript 将内部表示抽象掉 - 所以您认为的
Number 值的简单数组在内部可能是哈希映射或向量(尽管它的行为相同)。