d如何实现动态栈分配数组

原文

struct A {}
struct B { A a; }
struct C { A a; }

A*[] structs;

B b;
init(&b);
structs ~= cast(A*)&b;

错误:复制cast(A*)&b到分配内存中会逃逸b局部变量引用

C c;
init(&c);
structs ~= cast(A*)&c;
batch_process(structs);//最后

错误:复制cast(A*)&c到分配内存中会逃逸c局部变量引用

这样:cast(A*)&b.a?

如果确实想把对象放置在堆中.动态数组提供GC拥有的"内存".
以下程序交替把B和C放入缓冲区,然后批处理:

struct A { int i; }
struct B { A a; }
struct C { A a; }

A*[] structs;

void append(T, Args...)(ref ubyte[] structs, Args args) {
  import std.conv : emplace;

  structs.length += sizeWithPadding!T;
  auto where = cast(T*)(&structs[$ - sizeWithPadding!T]);
  emplace(where, args);
}

void main() {
  ubyte[] structs;

  foreach (i; 0 .. 10) {
    if (i % 2) {
      structs.append!B(A(i));

    } else {
      structs.append!C(A(i));
    }
  }

  batch_process(structs);
}

auto process(T)(const(ubyte)[] structs) {
  import std.stdio : writeln;

  writeln(*cast(T*)structs.ptr);
  return structs[sizeWithPadding!T..$];
}

void batch_process(const(ubyte)[] structs) {
  import std.range : empty;

  for (size_t i = 0; !structs.empty; i++) {
    if (i % 2) {
      structs = structs.process!B();

    } else {
      structs = structs.process!C();
    }
  }
}

T * nextAlignedAddress(T)(T * candidateAddr) {
  import std.traits;

  static if (is (T == class)) {
    const alignment = classInstanceAlignment!T;

  } else {
    const alignment = T.alignof;
  }

  const result = (cast(size_t)candidateAddr + alignment - 1)
                 / alignment * alignment;
  return cast(T*)result;
}

void * nextAlignedAddress(T)(void * candidateAddr) {
  return nextAlignedAddress(cast(T*)candidateAddr);
}

size_t sizeWithPadding(T)() {
  static if (is (T == class)) {
    const candidateAddr = __traits(classInstanceSize, T);

  } else {
    const candidateAddr = T.sizeof;
  }

  return cast(size_t)nextAlignedAddress(cast(T*)candidateAddr);
}

从这里复制了nextAlignedAddresssizeWithPadding函数.

我知道,垃集分配动态数组且禁止在垃集内存中保存局部变量引用,但是这里假设structs不会逃逸,可用固定大小数组实现:

A*[32] structs;
int i = 0;
structs[i++] = cast(A*)&b;

但是我想知道是否有具有最大容量限制可像普通动态数组一样连接的栈分配数组.
类似:

assumeNoEscapeOrWhatever!
DynamicArray structs;
structs ~= cast(A*)&b;

这就是@trusted的目的.也是为什么应小心使用它,并尽量最小化代码.

struct A {}
struct B { A a; }
struct C { A a; }

void main()
{
    A*[] structs;

    B b;
    C c;

    () @trusted {
        structs ~= cast(A*)&b;
        structs ~= cast(A*)&c;
    } ();
}

这是我要的,但为何

void func() @trusted
{
    A*[] structs;
    B b;
    structs ~= cast(A*)&b; // 仍然错误
}

不工作呢?

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