d动态数组容量

原文

string str = "0123456789ABCDEF";
char[] chr = str.dup;

assert(str.length == 16);
assert(str.capacity == 0);

import std.math: thus = nextPow2; //.algebraic

assert(chr.capacity == thus(str.length) - 1);
assert(chr.capacity == 31);

动态数组,按2的指数增长分配,而串不一样?
另外,.ptr保存最近的第一个元素地址,对吗?

write("str[0]@", &str[0]);
writeln(" == @", str.ptr);

write("chr[0]@", &chr[0]);
writeln(" == @", chr.ptr);

你已用串字面初化了str.GC不这样为他们分配内存.它们存储在二进制文件中,操作系统从磁盘加载他们到内存中.所以str.ptr指向固定大小静态内存位置,因此无额外容量.
chr使用(可改变的)运行时算法GC分配.更具体地说,指向已分配内存块起始地址.

给定T[]类型的ts实例,访问数组本质如下:

ts[0] == *(ts.ptr + 0);
ts[1] == *(ts.ptr + 1);
ts[2] == *(ts.ptr + 2);

由于T的大小是已知的,因此每次加指针都会增加N*T.sizeof字节.如果转换为ubyte数组,则需要自己处理.同样,&ts[0]==&(*ts.ptr + 0)==ts.ptr==&(*(ts.ptr+0)).
容量是,追加无需重新分配的可存储多少个数组元素.

为什么串字面0?因为它不从GC分配,因此没有附加的容量(请注意,即使串当前16个字符,也会返回0容量).
为什么垃集分配的数组是31?这是实现细节:
GC按2的指数(大部分)分配,最小块为16字节,下个大小为32字节.
为了记住用了哪个块,要分配空间来记录它.对16字节的块,需要1个字节.因而31,还有1字节用于记录.
串是,长度加指针而已.str.ptr是串第一个元素的指针.没有"最近第一个元素"的概念.

import std.range;
import std.stdio;

/* 切换数组

alias chr = char*;
auto data = [' '];/*/

alias chr = immutable(char*);
auto data = " ";//*/

void main()
{
  chr[] ptrs;
  data.fill(3, ptrs);

  writeln;
  foreach(ref ptr; ptrs)
  {
    " 0x".write(ptr);
  }
} /* 打印:

 0:           0 1:          15 2:          31 3:          47
 0x55B07E227020 0x7F2391F9F000 0x7F2391FA0000 0x7F2391FA1000
//*/


void fill(R)(ref R mostRecent, int limit, ref chr[] ptrs)
{
  auto ptr = mostRecent.ptr;
  size_t capacity, depth;

  while (depth <= limit)
  {
    mostRecent ~= ElementType!R.init;

    if(ptr != mostRecent.ptr)
    {
      ptrs ~= ptr;
      depth.writef!"%2s: %11s"(capacity);
      depth++;
    }

    if (mostRecent.capacity != capacity)
    {
      ptr = mostRecent.ptr;
      capacity = mostRecent.capacity;
    }
  }
}
posted @   zjh6  阅读(9)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示