好的。一般来说,我建议不要使用 immutable 成员的结构。有太多地方可以分配给一个有用的地方。您通常想要对结构执行的操作是使其成为可变的,const 或 immutable 作为一个整体。在大多数情况下,这很有效。例如
struct Foo
{
int i;
this(int j) { i = j; }
this(Foo rhs) { this = rhs; }
}
void main()
{
immutable f = Foo(5);
}
编译得很好。通常会导致问题的一个领域是当你必须有一个 postblit 构造函数时,因为它们目前不适用于 const 或 immutable 结构(这是非常需要修复的东西,但它仍然是一个开放的由于类型系统的工作方式导致的问题 - 它可能导致我们不得不向语言添加复制构造函数,或者我们可能会弄清楚如何去做,但现在它不起作用,而且可能很烦人)。但这仅在您需要 postblit 构造函数时才会影响您,而大多数结构不需要该构造函数(不过,问题最终会得到解决,因为它确实需要;这只是如何以及何时的问题)。
但是,为了更笼统地回答您的问题,让我们看一个类。例如,这段代码无法编译,因为构造函数不是immutable,并且编译器无法将immutable 类对象转换为可变对象(它可以使用结构来做到这一点,因为它会复制,但是对于一个类,它只是复制引用,而不是对象,所以它不起作用):
class Foo
{
int i;
this(int j) { i = j; }
}
void main()
{
auto f = new immutable Foo(5);
}
您会得到这个可爱的错误消息,而不是编译:
q.d(10): Error: mutable method q.Foo.this is not callable using a immutable object
q.d(10): Error: no constructor for Foo
有三种方法可以解决这个问题。首先是让构造函数immutable
class Foo
{
int i;
this(int j) immutable { i = j; }
}
这行得通,但它使您只能构造Foos,即immutable,这通常不是您想要的(尽管有时是)。因此,解决问题的第二种方法是将第一种解决方案更进一步并重载构造函数。例如
class Foo
{
int i;
this(int j) { i = j; }
this(int j) immutable { i = j; }
}
但是,这需要重复代码,这在此处并不多,但对于其他类型可能会很多。所以,一般最好的解决方案是让构造函数pure。
class Foo
{
int i;
this(int j) pure { i = j; }
}
这行得通,因为编译器知道没有任何东西逃脱了构造函数(因为pure保证没有任何东西通过分配给全局或静态变量来逃脱,并且构造函数的参数也不允许任何东西逃脱),并且因为它知道没有对Foo 或其成员的引用可以逃脱构造函数,所以它知道没有其他对这个Foo 的引用,因此它可以安全地将其转换为可变的const 或@987654342 @ 不违反类型系统。当然,只有当你可以使构造函数pure并且没有任何东西可以通过构造函数的参数逃逸时,这才有效,但通常是这种情况,当它不是,你总是可以在可变性上重载构造函数,尽管这是不太可取的。
如果你真的想要const 或immutable 成员,可以在结构上使用相同的技术,但我再次建议不要这样做。这只会给您带来更多麻烦,尤其是在声明变量时只创建整个结构 const 或 immutable 通常是微不足道的。