[英]Immutability in D constructors
我之前的問題討論過如下制作復制構造函數:
struct Foo {
int i;
this(int j) { i = j; }
this(Foo rhs) { this = rhs; }
}
void main()
{
auto f = Foo(5);
auto g = new Foo(f);
}
但是,如果我使i
不可變,構造函數無法編譯
錯誤:無法使用不可變成員修改struct this Foo
為什么會這樣? 我的印象是,在到達構造函數的末尾之前,類或結構的不可變成員不會變為不可變。
好的。 一般來說,我建議不要使用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; }
}
這是有效的,但它使得你只能構造immutable
Foo
,這通常不是你想要的(雖然它有時是)。 因此,解決問題的第二種方法是將第一個解決方案更進一步,並使構造函數重載。 例如
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
引用,因此它可以安全地將其轉換為mutable, const
或immutable
而不違反類型系統。 當然,這只有在你可以使構造函數pure
並且沒有任何東西可以通過構造函數的參數進行轉義時才有效,但通常就是這種情況,當它不存在時,你總是可以在可變性上重載構造函數,就像那樣不太可取。 。
如果你真的想要const
或immutable
成員,可以在結構上使用相同的技術,但同樣,我建議反對它。 這只會給你帶來更多的麻煩而不是它的價值,特別是在聲明一個變量時,只需要使整個struct const
或immutable
一般都是微不足道的。
使結構成員immutable
停止分配給結構,這反過來會導致相當多的問題,你可能會重新考慮這一點。
否則直接分配成員而不是依賴賦值運算符:
struct Foo {
immutable int i;
this(int j) { i = j; }
this(in Foo rhs) { this.i = rhs.i; }
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.