4

D中函数参数的存储类说明符比较多,分别是:

  • 没有任何
  • in(相当于const scope
  • out
  • ref
  • scope
  • lazy
  • const
  • immutable
  • shared
  • inout

他们背后的理性是什么?他们的名字已经提出了明显的用途。但是,有一些悬而未决的问题:

  1. 我应该默认使用ref与类型函数参数结合in使用吗?struct
  2. 是否out隐含ref暗示?
  3. 我什么时候应该使用none
  4. 类和/或接口是否ref有意义?(类类型默认为引用。)
  5. ref在数组切片上怎么样?
  6. 我应该const尽可能使用内置算术类型吗?

更笼统地说:在内置类型、数组、结构、类和接口的情况下,何时以及为什么应该对函数参数类型使用哪个存储类说明符?(为了稍微隔离问题的范围,请不要讨论shared,因为它有自己的孤立含义。)

4

1 回答 1

4
  1. 我不会默认使用任何一个。ref参数只接受左值,这意味着您将更改传入的参数。如果您想避免复制,请使用const refor auto ref。但const ref 仍然需要一个左值,所以除非你想复制你的函数,否则它通常比它的价值更烦人。虽然auto ref会避免复制左值(它基本上使得它有一个版本的函数,它接受一个ref左值,一个接受右值而不接受ref),它只适用于模板,限制了它的有用性。由于 D是可传递的,并且丢弃是未定义的行为,因此使用const可能会产生深远的影响constconst从变量中修改它。因此,虽然它通常很有用,但默认使用它可能会给您带来麻烦。

    Usingin给你scope除了const,我通常不建议这样做。scopeon function parameters 应该做到这一点,这样对该数据的引用就不会逃脱该函数,但是对它的检查尚未正确实现,因此您实际上可以在比应该合法的更多情况下使用它。在某些情况下scope是无价的(例如,使用委托,因为它使编译器不必为其分配闭包),但对于其他类型,它可能很烦人(例如,如果您传递一个数组 be scope,那么你不能从函数返回一个切片到该数组)。并且任何具有任何数组或引用类型的结构都会受到影响。虽然您不会收到很多关于错误使用的投诉scope现在,如果你一直在使用它,一旦它被修复,你肯定会遇到很多错误。此外,它对值类型完全没有意义,因为它们没有转义的引用。因此,在值类型(包括作为值类型的结构)上使用const和实际上是相同的。in

  2. out与它相同,ref只是它将参数重置为其init值,以便无论传入的变量的先前状态是什么,您总是得到相同的传入值。

  3. 几乎总是就函数参数而言。当您有特定需要时,您可以使用constor scopeor whatnot,但我不建议默认使用它们中的任何一个。

  4. 当然可以。ref与类引用的概念是分开的。这是对传入变量的引用。如果我这样做

    void func(ref MyClass obj)
    {
        obj = new MyClass(7);
    }
    
    auto var = new MyClass(5);
    func(var);
    

    new MyClass(7)然后 var 将在调用后引用新构造的func而不是new MyClass(5). 您通过ref. 这就像获取引用的地址(如var)如何为您提供指向引用的指针而不是指向类对象的指针。

    MyClass* p = &var; //points to var, _not_ to the object that var refers to.
    
  5. 与类的处理相同。ref使参数引用传入的变量。例如

    void func(ref int[] arr)
    {
        arr ~= 5;
    }
    
    auto var = [1, 2, 3];
    func(var);
    assert(var == [1, 2, 3, 5]);
    

    如果func不接受它的论点ref,则将var被切片,并且附加到arr不会影响var. 但是由于参数是ref,所以对 所做的任何事情arr都是对var

  6. 这完全取决于你。制作它const使您无法对其进行变异,这意味着如果您不打算对其进行变异,您可以避免意外变异它。它也可能会启用一些优化,但是如果您从不写入变量,并且它是一个内置的算术类型,那么编译器就知道它永远不会被更改,并且优化器应该能够进行这些优化(尽管它是否或不取决于编译器的实现)。

    immutable并且const在几乎所有情况下对于内置算术类型实际上都是相同的,所以就个人而言,immutable如果我想保证这样的变量不会改变,我只会使用它。一般来说,使用immutable而不是constif you can 可以为您提供更好的优化和更好的保证,因为它允许变量在线程之间隐式共享(如果适用)并且它始终保证变量不能被变异(而对于引用类型,const只是意味着该引用不能改变对象,而不是不能改变)。

    当然,如果你尽可能多地标记你的变量,那么它至少在某些时候确实有助于编译器进行优化,并且它可以更容易地捕获你无意中改变某些东西的错误constimmutable它还可以使您的代码更易于理解,因为您知道该变量不会发生变异。因此,自由地使用它们可能很有价值。但同样,根据类型使用constorimmutable可能会受到过度限制(尽管这不是内置整数类型的问题),因此只需自动将所有内容标记为constorimmutable可能会导致问题。

于 2012-08-29T17:36:30.550 回答