Разница между 'const ref' и 'in'?

Я пытаюсь понять разницу между const ref и in, особенно когда дело доходит до производительности.

  • Я знаю, что 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).? пример кода приветствуется.

  • Как мне выбрать между const ref и in при реализации функции? Я знаю, что с ref объект не копируется, потому что он ссылается, но имеет то же значение с in?

Ответы

Ответ 1

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 не используется для обновления исходного значения.

Ответ 2

  • Это не легально для параметров scope для выхода из функции. Предполагается, что компилятор гарантирует, что никакие ссылки на эти данные не выйдут из функции. Он используется в основном с делегатами, поскольку он позволяет компилятору избегать выделения замыкания, поскольку он знает, что делегат не уйдет.

  • const ref - const - точно так же, как in, но переменная передается по ссылке вместо копирования, поэтому вы избегаете копирования. Однако в отличие от С++ const ref не работает с rvalues. Ему нужно дать lvalue. Итак, если вы объявляете параметр 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 могут использовать только глобальные переменные, если они являются неизменяемыми или являются типами значений и являются константами), поэтому pure обычно дает вам все, что вам нужно для параметров, которые являются классами и массивами. Кроме того, если тип возврата является классом или массивом, вы вообще не хотите его делать, чтобы аргументы не могли убежать, потому что вместо того, чтобы повторно использовать что-либо из этих аргументов в возвращаемом значении, функция вынужден сделать копию, которая, как правило, менее эффективна.

Итак, scope обычно используется только с делегатами, но порой полезен для классов или массивов. В любом случае, как правило, предпочтительнее, чтобы функции были pure, так что заботятся о большей части проблемы. Как таковой, хотя использовать in не повредит, часто бывает мало смысла использовать in вместо const. И вы обычно используете только const ref, если вы действительно хотите избежать копирования передаваемой переменной, потому что в противном случае вы можете передавать только lvalues ​​этой функции. Вы можете перегрузить функцию таким образом, чтобы она имела версию, которая принимает const и одну, которая принимает const ref, но это, очевидно, приводит к дублированию кода, поэтому, если вы действительно не хотите const ref, возможно, лучше всего использовать const.

EDIT:

scope еще предстоит реализовать для чего угодно, кроме делегатов (по состоянию на 2013-06-18), поэтому использование scope или in с чем-либо, кроме делегатов, не рекомендуется. На данный момент они вводят в заблуждение, и если/раз scope реализовано для чего угодно, кроме делегатов, существует высокий риск того, что ваш код сломается из-за ссылок на переменные, помеченные экранированием scope или in.