我正在尝试理解const ref
和in
之间的区别,特别是在性能方面。
我知道in
相当于const scope
,但the scope storage class means that references in the parameter cannot be escaped (e.g. assigned to a global variable).
是什么意思?欢迎使用示例代码。
在实现功能时,如何在const ref
和in
之间做出决定?我知道ref
对象没有被复制,因为它是一个引用,但in
也是如此?
答案 0 :(得分:11)
1)scope
参数存储类意味着您不允许转义对参数的引用。例如:
Object glob;
struct S
{
Object o;
void foo(scope Object o)
{
this.o = o; // Not allowed! 'o' must not be escaped
glob = o; // ditto
}
}
请注意,DMD在检测时并不是很擅长。上面的例子目前正在编译,但是不允许。
scope
对委托参数最有用:
void foo(scope void delegate() dg)
{
/* use dg */
}
void main()
{
int i;
foo({ ++i; });
}
在上面的例子中,不需要为匿名函数分配闭包,即使它有一个upvalue,因为foo
“保证”(这是编译器的工作...)委托不是逃过一劫。 DMD目前正在实施此优化。
2)我认为这个想法是当使用const
和scope
时,编译器理论上可以随意通过引用或值传递,这就是in
快捷方式的原因。有用。 DMD现在没有利用这一点,但它仍然是一个方便的捷径,它有一些文档价值。
简而言之,in
目前不会获得任何表现,除非它在代表身上使用。 ref
可以通过大型结构或静态数组获得一些性能。出于性能原因使用ref
时,const
通常用于记录(并强制执行)ref
不用于更新原始值。< / p>
答案 1 :(得分:11)
scope
参数转义函数是不合法的。编译器应该保证不会对该数据的引用转义该函数。它主要用于委托,因为它允许编译器避免分配闭包,因为它知道委托不会逃脱。
const ref
是const
- 就像in
一样 - 但变量是通过引用传递而不是复制的,因此您可以避免复制。但是,与C ++ const ref
不同,不与rvalues一起使用。 必须给予左值。因此,如果您将参数声明为const ref
,那么它将限制您传递给它的内容。您通常必须声明要传递给它的变量,而in
将接受临时变量。
void func(const ref int var) {}
int a;
func(a); //legal
func(7); //illegal
如果func
占用const
或in
,这两个电话都是合法的。因此,一般来说,问题不在于您是应该使用const ref
还是in
。问题是您是应该使用const
还是in
。在这种情况下,问题是您是否要使用scope
,因为它们都是const
。如果你想确保没有引用你传入的变量的引用将转义该函数,你使用scope
,因此它通常只用于代理,但对类或数组可能有用。
但是,函数上的pure
保证除了通过返回值之外,对其任何参数的引用都不能转义(因为pure
函数只能使用全局变量,如果它们是不可变的或者是值的类型并且是const),因此pure
通常为您提供类和数组参数所需的所有内容。另外,如果返回类型是一个类或数组,你通常不希望这样做,以便参数不能转义,因为它不是能够在返回值中重用那些参数中的任何东西,而是函数被迫制作副本,这通常效率较低。
因此,scope
通常仅与代理一起使用,但有时对类或数组很有用。函数通常最好是pure
,因此可以解决大部分问题。因此,尽管使用in
并没有什么坏处,但使用in
代替const
通常没什么意义。如果你真的想避免复制传入的变量,通常只使用const ref
,否则你只能将lvalues传递给该函数。 可以重载一个函数,使其具有const
版本和const ref
版本,但这显然导致代码重复,所以除非你真的想要{{1最好使用const ref
。
修改强>
const
尚未针对除代表之外的任何内容实施(截至2013-06-18),因此使用scope
或scope
以及代理以外的任何内容都是错误的建议。目前,它们具有误导性,如果/ in
实施除代理以外的任何事情,则由于引用标有scope
或{的变量,您的代码很可能会中断{1}}逃避。