D中的函数参数有相对多的存储类说明符,它们是:
in
(相当于const scope
)out
ref
scope
lazy
const
immutable
shared
inout
他们背后的理性是什么?他们的名字已经提出了明显的用途。但是,有一些悬而未决的问题:
ref
与in
结合使用struct
类型的函数参数吗? out
暗示ref
是否含蓄?ref
是否有意义? (默认情况下,类类型是引用。)ref
怎么样?const
内置算术类型吗?更一般地说:在内置类型,数组,结构,类和接口的情况下,何时以及为什么我应该使用哪个存储类说明符用于函数参数类型?
(为了稍微区分问题的范围,请不要讨论shared
,因为它有其独立的含义。)
答案 0 :(得分:4)
默认情况下我也不会使用。 ref
参数只接受左值,这意味着你将改变传入的参数。如果你想避免复制,那么使用const ref
或auto ref
。但是const ref
仍然需要一个左值,所以除非你想要复制你的函数,否则它通常比它的价值更令人讨厌。虽然auto ref
将避免复制左值(它基本上使得它有一个函数的版本,它采用ref
的左值和一个不使用ref
的rvalues,它只能工作使用模板,限制其有用性。使用const
可能会产生深远的影响,因为D const
具有传递性,并且事实上,从变量中抛弃const
并修改它是未定义的行为。因此,虽然它通常很有用,但默认使用它可能会让你陷入困境。
使用in
除scope
之外还提供const
,我通常会建议您这样做。关于函数参数的scope
应该使它不会引用该数据,但是对它的检查还没有正确实现,所以实际上你可以在很多情况下使用它。应该是合法的。在某些情况下,scope
是无价的(例如,使用委托,因为它使得编译器不必为它分配闭包),但对于其他类型,它可能很烦人(例如,如果你传递一个数组scope
,然后你不能从该函数返回一个切片到该数组)。任何包含任何数组或引用类型的结构都会受到影响。虽然你现在不会对错误地使用scope
提出很多抱怨,但如果你一直在使用它,那么一旦修复它就会遇到很多错误。此外,它对于值类型完全没有意义,因为它们没有提到逃避。因此,在值类型(包括值类型的结构)上使用const
和in
实际上是相同的。
out
与ref
相同,只是它将参数重置为其init
值,这样无论先前的状态如何,您都会获得相同的值传入的变量是。
几乎总是就函数参数而言。如果您有特殊需要,可以使用const
或scope
或其他内容,但默认情况下我不建议使用其中任何一个。
当然可以。 ref
与类引用的概念是分开的。它是对传入的变量的引用。如果我这样做
void func(ref MyClass obj)
{
obj = new MyClass(7);
}
auto var = new MyClass(5);
func(var);
然后var将在调用new MyClass(7)
而不是func
之后引用新构建的new MyClass(5)
。您正在通过ref
传递引用。这就像获取引用的地址(如var
)为您提供指向引用的指针以及而不是指向类对象的指针一样。
MyClass* p = &var; //points to var, _not_ to the object that var refers to.
与班级相同的交易。 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
完成。
这完全取决于你。使它成为const
使得你不能改变它,这意味着如果你不打算改变它,你就会受到保护而不会意外地改变它。 可能也可以启用一些优化,但是如果你从不写入变量,并且它是内置的算术类型,那么编译器知道它永远不会改变,优化器应该能够进行那些优化无论如何(不管它是否取决于编译器的实现)。
immutable
和const
对于内置算术类型实际上是相同的,所以就我个人而言,如果我想保证这样的话,我只会使用immutable
变量不会改变。通常,使用immutable
而不是const
如果可以为您提供更好的优化和更好的保证,因为它允许变量在线程之间隐式共享(如果适用)并且总是保证变量不能被变异(而对于引用类型,const
仅仅意味着该引用不能改变对象,而不是它不能被变异)。
当然,如果你尽可能地标记变量const
和immutable
,那么它确实至少在某些时候帮助编译器进行优化,并且它可以更容易地捕获错误当你不是故意的时候,你突然改变了什么。它还可以使您的代码更容易理解,因为您知道变量不会被变异。因此,大量使用它们可能很有价值。但同样,使用const
或immutable
可能过于严格,具体取决于类型(尽管这不是内置整数类型的问题),因此只需将所有内容自动标记为{{1} }或const
会导致问题。