繁体   English   中英

我应该如何在D中的函数参数中使用存储类说明符,如ref,in,out等?

[英]How should I use storage class specifiers like ref, in, out, etc. in function arguments in D?

D中的函数参数有相对多的存储类说明符,它们是:

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

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

  1. 默认情况下,我应该使用ref结合in for struct type函数参数吗?
  2. 难道out暗示ref隐含?
  3. 什么时候应该使用没有
  4. 类和/或接口上的ref是否有意义? (默认情况下,类类型是引用。)
  5. 如何对阵列切片进行ref
  6. 我应该尽可能使用const作为内置算术类型吗?

更一般地说:在内置类型,数组,结构,类和接口的情况下,何时以及为什么我应该使用哪个存储类说明符用于函数参数类型? (为了稍微区分问题的范围,请不要讨论shared ,因为它有其独立的含义。)

  1. 我不会默认使用。 ref参数只接受左值,这意味着你将改变传入的参数。如果你想避免复制,那么使用const refauto ref 但是const ref 仍然需要一个左值,所以除非你想复制你的函数,否则它通常比它的价值更令人讨厌。 auto ref将避免复制左值(它基本上使得它有一个函数的版本,它接受ref的lvalues和一个不带ref rvalues),它只适用于模板,限制了它的用处。 使用const会产生深远的影响,因为D的const是可传递的,并且事实上它是从变量中抛弃const并修改它的未定义行为。 因此,虽然它通常很有用,但默认使用它可能会让你陷入困境。

    使用inconst提供scope ,我通常建议不要使用const 函数参数的scope应该使它不会引用该数据,但是对它的检查还没有正确实现,所以你实际上可以在很多情况下使用它而不是合法的。 在某些情况下, scope是非常宝贵的(例如,使用委托,因为它使得编译器不必为它分配闭包),但对于其他类型,它可能很烦人(例如,如果传递数组是scope ,然后您无法从该函数返回切片到该数组)。 任何包含任何数组或引用类型的结构都会受到影响。 虽然你现在不会有很多关于错误使用scope抱怨,如果你一直在使用它,你一定会在修复后遇到很多错误。 此外,它对于值类型完全没有意义,因为它们没有提到逃避。 因此, in值类型(包括值类型的结构)上使用constin实际上是相同的。

  2. outref相同,只是它将参数重置为其init值,这样无论传入的变量的先前状态如何,您始终都会获得相同的值。

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

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

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

    然后var将在调用func而不是new MyClass(5)之后引用新构造的new MyClass(7) 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使得你不能改变它,这意味着如果你不打算改变它,你就会受到保护而不会意外地改变它。 可以启用一些优化,但是如果你从不写入变量,并且它是内置的算术类型,那么编译器就知道它永远不会改变,优化器应该能够进行那些优化(不管它是否确实如此)不取决于编译器的实现)。

    对于几乎所有情况下的内置算术类型, immutableconst实际上是相同的,所以我个人认为,如果我想保证这样的变量不会改变,我只使用immutable变。 通常,如果可以使用immutable而不是const则可以为您提供更好的优化和更好的保证,因为它允许跨线程隐式共享变量(如果适用),并且它始终保证变量不能被变异(而对于参考) types, const只表示该引用不能改变对象,而不是它不能被改变)。

    当然,如果你尽可能地标记你的变量constimmutable ,那么它确实至少在某些时候帮助编译器进行优化,并且它可以更容易地捕获你不想改变的东西。 它还可以使您的代码更容易理解,因为您知道变量不会被变异。 因此,大量使用它们可能很有价值。 但同样,使用constimmutable可能过于严格,具体取决于类型(虽然这不是内置整数类型的问题),因此只需将所有内容自动标记为constimmutable就会导致问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM