2013-05-20 98 views

回答

12

這是一個比最初期望的更棘手的情況之一。

D對C++的重要和有用的特性之一是每一種類型(包括所有的用戶類型)都有一些可以在編譯時評估的初始非垃圾值。它是用來作爲T.init,有兩個重要的用途:

  1. 模板約束可以使用T.init值來檢查,如果某些操作可以在給定類型進行(引用原賢治的片段):

    template isSomething(T) { 
        enum isSomething = is(typeof({ 
         //T t1;      // not good if T is nested struct, or has @disable this() 
         //T t2 = void; auto x = t2; // not good if T is non-mutable type 
         T t = T.init;    // avoid default construct check 
         ...use t... 
        })); 
    } 
    
  2. 除非明確使用int i = void語法,否則您的變量始終會被正確初始化。沒有垃圾可能。

鑑於此,出現了難題。我們是否應該保證T()和T.init是相同的(因爲許多來自C++的程序員會期望)或者允許可能容易破壞該保證的默認構造。據我所知,做出的決定是,儘管令人驚訝,但第一種方法更安全。然而,討論不斷出現各種改進建議(例如,允許CTFE可以使用的默認構造函數)。一個such thread已經出現在最近。

8

它源於D中的所有類型必須具有默認值的事實。在類型的init值有很多地方被使用,其中包括像默認初始化成員變量這樣的東西,以及在分配時默認初始化數組中的每個值,並且編譯時需要知道init。有init提供了很多好處,但它確實阻礙了默認的構造函數。

一個真正的默認構造函數就不需要在所有使用init的地方使用(或它不會是默認值),但允許任意代碼在的一定數量的init使用的情況下運行會充其量是有問題的。至少,你可能會被迫使它成爲CTFE能力,並可能是pure。只要你開始對它進行限制,很快你就可以直接將所有成員變量初始化爲你想要的(這是init的情況),因爲你不會獲得太多(如果有的話),這將使默認的構造函數非常無用。

可能可以同時擁有init和默認構造函數,但隨後的問題來了作爲一個時使用過其他的,並且默認的構造函數不會真的是默認了到。更不用說,開發人員可能會對使用init值的時間以及何時使用默認構造函數感到困惑。現在

,我們@disable一個struct的init值(這將導致其自身的問題),在這種情況下,這將是非法的使用結構中,需要init任何局勢的能力。因此,可能有一個默認的構造函數可以在運行時運行任意代碼,但是我不知道這個結果的確切後果。然而,我確信有些情況下人們會希望有一個默認的構造函數,需要init,因此它不起作用,因爲它是@disabled(像聲明類型的數組可能是其中之一)。

因此,正如您所看到的,通過執行D與init所做的操作,使默認構造函數的整個問題比其他語言更加複雜和有問題。

獲取類似於默認構造的常規方法是使用靜態的opCall。喜歡的東西

struct S 
{ 
    static S opCall() 
    { 
     //Create S with the values that you want and return it. 
    } 
} 

然後,每當你使用S() - 例如

auto s = S(); 

,靜態opCall被調用,你會得到這是在運行時創建的值。但是,S.init仍將用於之前的任何位置(包括S s;),並且僅在明確使用S()時纔會使用靜態opCall。但是,如果你將它與@disable this()(它禁用了init屬性)相結合,那麼你就會得到類似於我之前描述的,我們可能使用@disabled init的默認構造函數。

我們可能會或可能不會與缺省構造被添加到最終的語言結束了,但還有一些技術問題,他們將因如何init和語言文字工作,和沃爾特亮不認爲他們應該被添加。因此,對於默認的構造函數加入到語言中,有人必須提出一個非常有吸引力的設計,以適當解決所有問題(包括說服Walter),並且我並不期望這樣做,但我們會看到。

相關問題