2013-05-20 100 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),并且我并不期望这样做,但我们会看到。

相关问题