簡體   English   中英

D構造函數的不變性

[英]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成員。 有太多的地方可以分配給一個有用的地方。 你通常想要對結構做什么是使它成為一個整體可變, constimmutable的。 而在大多數情況下,這才有效。 例如

struct Foo
{
    int i;

    this(int j) { i = j; }

    this(Foo rhs) { this = rhs; }
}

void main()
{
    immutable f = Foo(5);
}

編譯得很好。 通常會導致問題的一個方面是當你必須有一個postblit構造函數時,因為那些當前不使用constimmutable結構(這是一個非常需要修復的東西,但它仍然是一個開放的問題,因為如何類型系統工作 - 它可能導致我們不得不在語言中添加復制構造函數,或者我們可能會弄清楚如何執行它,但是現在,它不起作用,並且它可能很煩人)。 但是這只會影響你,如果你需要一個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, constimmutable而不違反類型系統。 當然,這只有在你可以使構造函數pure並且沒有任何東西可以通過構造函數的參數進行轉義時才有效,但通常就是這種情況,當它不存在時,你總是可以在可變性上重載構造函數,就像那樣不太可取。 。

如果你真的想要constimmutable成員,可以在結構上使用相同的技術,但同樣,我建議反對它。 這只會給你帶來更多的麻煩而不是它的價值,特別是在聲明一個變量時,只需要使整個struct constimmutable一般都是微不足道的。

使結構成員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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM