访问D中范围内的元素

Sti*_*ode 0 struct associative-array d

我正在编写我的第一个D程序,并试图了解如何实现关联数组.不断出现的问题是,如果我创建一个像这样的数组:

import std.stdio;
import std.string;
import std.array;

void main(string[] args) { 
   int[string] arr = ["first" : 1, "second" : 2]; 
}
Run Code Online (Sandbox Code Playgroud)

一切都很好.但如果我尝试将arr移动到main之外 - 进入结构体,我会收到错误说:错误:非常量表达式.

这会引发错误:

import std.stdio;
import std.string;
import std.array;

struct foo {
int[string] arr = ["first" : 1, "second" : 2]; 
}

void main(string[] args)
{ /* do stuff with foo */ }
Run Code Online (Sandbox Code Playgroud)

我确定这是一个非常简单的修复,但这是我第一次尝试D.

Mih*_*uns 5

这种限制来自D模块中的符号不​​是有序但存在"并行"的事实.这通常是一件好事,因为:

  • 编译器可以并行进行语义分析
  • 你不需要显式的前向声明(比如在C中)来使用模块中稍后声明的符号

考虑到这一点,请考虑此代码(全局范围):

int x;
int foo() { return ++x; }
int y1 = foo();
int y2 = foo();
Run Code Online (Sandbox Code Playgroud)

如果允许初始化程序使用运行时代码,则值y1y2将取决于一般未定义的评估顺序 - 所有全局变量都是"相等".

但是对于局部函数变量,没有这样的问题 - 它们被放置在堆栈上,因此评估的顺序是完美定义的(它是按词汇顺序):

void foo()
{
    int x;
    int foo() { return ++x; }
    int y1 = foo(); // will always be 1
    int y2 = foo(); // will always be 2
}
Run Code Online (Sandbox Code Playgroud)

因为在使用globals或struct字段的初始化程序语法时,编译器将限制为仅编译时常量.构造函数(包括模块构造函数)仍然可以:

int[int] x;

static this()
{
    x = [ 1 : 1, 2 : 2 ];
}
Run Code Online (Sandbox Code Playgroud)

AA文字可能看起来像一个适当的常量,但它实际上需要从运行时堆分配内存.D很聪明,可以接受一些这样的实体(甚至是某些类)并将它们放在固定的二进制内存部分,但AA可以扩展,因此需要适当的动态堆.

另请注意,struct在D中不能有默认构造函数:

struct foo
{
    int[string] arr;
    // this won't work:
    this() { this.arr = ["first" : 1, "second" : 2]; }
}

// need class instead

class boo
{
    int[string] arr;
    // fine:
    this() { this.arr = ["first" : 1, "second" : 2]; }
}
Run Code Online (Sandbox Code Playgroud)