2015-03-31 104 views
0

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

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

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

一切都编译好。但如果我尝试并将arr移动到main之外 - 进入一个结构体,我得到一个错误:Error:非常量表达式。

,这将引发错误:

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 */ } 

我敢肯定,这是一个超级简单的修补程序,但是这是我在D.

第一次尝试
+1

我认为这个问题是结构尺寸在编译时进行计算,但关联数组没有分配,直到运行时和编译器不知道它的大小等。声明它为'enum'可能工作。我可能是错的,但我认为是这样。你也可以尝试制作一个构造函数。 – Bauss 2015-03-31 05:11:20

+0

我试着创建一个构造函数,并得到一个错误,说:结构的默认构造函数只允许与@disable和没有正文。所以我只是将数组设置为枚举,它似乎工作。 – StillLearningToCode 2015-03-31 05:20:44

+0

如果您希望在运行时定义AA,则必须创建一个接受参数的构造函数。即struct foo {this(int [string] _a){this。arr = a;否则,正如L33T所说的那样,在编译时使用enum来定义它。 Compile-Time vs Runtime是我学习D的最大的学习曲线,来自Java背景,至少在你没有的地方。这将需要一点习惯:)! – 2015-03-31 08:24:20

回答

5

此限制来自于这样一个事实,即D模块中的符号不​​是有序的,而是“并行”存在的。这通常是一件好事,因为:

  • 编译器能做语义分析并行
  • 你不(在C等)需要明确的向前声明使用后的模块中声明符号

考虑到这一点,考虑下面的代码(全球范围):使用运行时代码

int x; 
int foo() { return ++x; } 
int y1 = foo(); 
int y2 = foo(); 

如果被允许用于初始化的y1一个值nd y2将取决于通常未定义的评估顺序 - 所有全局变量都是“相等的”。

但对于本地函数变量不存在这样的问题 - 它们被放置在栈,从而评价顺序完全被定义(这是词汇顺序):

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

由于该编译器限制你当为全局或结构字段使用初始化语法时,只有编译时常量。构造函数(包括模块构造函数)仍然正常,但:

int[int] x; 

static this() 
{ 
    x = [ 1 : 1, 2 : 2 ]; 
} 

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]; } 
} 
2

像这样的事情会工作。

struct Foo{ 
    int[string] arr; 
} 

void main(){ 
    Foo foo = Foo(["first" : 1, "second" : 2]); 
}