'const ref'和'in'之间的区别?

时间:2011-12-15 05:32:57

标签: d

我正在尝试理解const refin之间的区别,特别是在性能方面。

  1. 我知道in相当于const scope,但the scope stor­age class means that ref­er­ences in the pa­ra­me­ter can­not be es­caped (e.g. as­signed to a global vari­able).是什么意思?欢迎使用示例代码。

  2. 在实现功能时,如何在const refin之间做出决定?我知道ref对象没有被复制,因为它是一个引用,但in也是如此?

2 个答案:

答案 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)我认为这个想法是当使用constscope时,编译器理论上可以随意通过引用或值传递,这就是in快捷方式的原因。有用。 DMD现在没有利用这一点,但它仍然是一个方便的捷径,它有一些文档价值。

简而言之,in目前不会获得任何表现,除非它在代表身上使用。 ref 可以通过大型结构或静态数组获得一些性能。出于性能原因使用ref时,const通常用于记录(并强制执行)ref 用于更新原始值。< / p>

答案 1 :(得分:11)

  1. scope参数转义函数是不合法的。编译器应该保证不会对该数据的引用转义该函数。它主要用于委托,因为它允许编译器避免分配闭包,因为它知道委托不会逃脱。

  2. const refconst - 就像in一样 - 但变量是通过引用传递而不是复制的,因此您可以避免复制。但是,与C ++ const ref不同,与rvalues一起使用。 必须给予左值。因此,如果您将参数声明为const ref,那么它将限制您传递给它的内容。您通常必须声明要传递给它的变量,而in将接受临时变量。

    void func(const ref int var) {}
    int a;
    func(a); //legal
    func(7); //illegal
    
  3. 如果func占用constin,这两个电话都是合法的。因此,一般来说,问题不在于您是应该使用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),因此使用scopescope以及代理以外的任何内容都是错误的建议。目前,它们具有误导性,如果/ in实施除代理以外的任何事情,则由于引用标有scope或{的变量,您的代码很可能会中断{1}}逃避。