2011-12-15 2 views
16

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

  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 ref и in при реализации функции? Я знаю, что с ref объект не копируется, потому что он является ссылкой, но является ли он таким же, как и с in?

ответ

10

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; }); 
} 

В приведенном выше примере, не закрытие не должно быть выделено для анонимной функции, даже если она имеет повышать стоимость, потому что foo «гарантия» (это компилятор ...), что делегат не сбежал. В настоящее время DMD реализует эту оптимизацию.

2) Я думаю, что идея заключается в том, что, когда оба const и scope используются, компилятор теоретически может пройти по ссылке или значения по желанию, из-за чего in ярлыка полезно. DMD не использует это прямо сейчас, но это удобный ярлык, тем не менее, и он имеет некоторую ценность для документации.

Короче говоря, in в настоящее время не получит вас никакой производительности, если только он не используется в делегате. refможет получить некоторую производительность с большими структурами или статическими массивами. Когда ref используется по соображениям производительности, const часто используется для документирования (и обеспечения исполнения), чтобы ref был , а не, используемый для обновления исходного значения.

+0

1. хороший, это объясняет, почему я не смог воспроизвести эффект. 2. Итак, вы говорите, что если параметр функции имеет '' 'класс хранения, он копируется? Должен ли я использовать 'const ref' тогда? – Arlen

+0

С текущим выбором компилятора, все на основе DMD, оно копируется. Но опрятная вещь в том, что она по-прежнему технически реализована, потому что пользователь не может сказать разницы. Для того, чтобы DMD воспользовался этим для оптимизации, он должен полностью реализовать «область» в первую очередь. Если вы определили копирование как узкое место и хотите оптимизировать, использование 'const ref' - хорошая идея. –

+0

Как вы так много знаете о DMD? вы один из основных разработчиков? – Arlen

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

  2. const ref является const - так же, как in бы - но переменная передается по ссылке, вместо того, чтобы быть скопированы, так вы избежите копию. Однако в отличие от C++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 ​​этой функции. You может перегрузить функцию таким образом, чтобы она имела версию, которая принимает const, и тот, который принимает const ref, но это, очевидно, приводит к дублированию кода, поэтому, если вы действительно не хотите const ref, это, вероятно, просто лучше всего использовать const.

EDIT:

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

+0

Не правда ли, что 'in' работает не так, как должно, потому что' scope' не полностью реализована в DMD? Разве это не было бы изменением, если «scope» будет полностью реализован для тех, кто неправильно использовал 'in'? – Arlen

+0

Предполагая, что 'scope' является ошибкой (и это может быть очень хорошо, я не использую его много, поэтому я не совсем уверен в его текущем состоянии), то да, это было бы изменением для любого кода, который использовать 'scope' или' in' неправильно, но это то же самое с почти любой ошибкой компилятора. К счастью, количество таких проблем в dmd значительно сократилось из-за быстрых темпов разработки с момента перехода на github, но, безусловно, все еще можно столкнуться с проблемами, когда функция не реализована правильно. –

+0

'scope' на самом деле не глючит, он просто не реализован вообще, кроме оптимизации. 'pure' редко является хорошей альтернативой' scope', потому что с помощью функции 'pure' member вы все равно можете избежать параметра, присвоив его полю элемента, а' pure' имеет другие, несвязанные ограничения. Если 'scope' был полностью реализован, это было бы полезно для большого количества случаев, например, чтобы безопасно передавать срезы для стека памяти для функции, получающей ее с помощью« scope ». –

Смежные вопросы