Вы действительно должны прочитать http://dlang.org/d-array-article.html. Он подробно рассказывает о том, как массивы в D работают. Но за короткий ответ, все, что получение копируются при передаче аргументов в
T[] add(T)(T[] a, T[] b) {...}
является основным указатель указателя и длиной. Ни один из элементов не копируется. Скорее, массив «нарезанный». Результирующие массивы внутри add
представляют собой фрагменты аргументов add
, что означает, что они относятся к той же памяти, что и исходные массивы. Мутирование элементов среза будет мутировать элементы исходного массива, потому что они являются одними и теми же элементами. Однако, мутируя сам массив (например, присваивая ему другой массив или добавляя к нему), не влияет на оригинал, и если добавление к массиву приводит к перераспределению его памяти, чтобы освободить место (или если новый массив назначен массив), то этот массив больше не будет ссылаться на те же элементы, что и у оригинала. Единственное место в вашем коде, которое копирует массив, составляет a.dup
.
Какая маркировка массивов ref
делает это так, чтобы они не были нарезаны. Скорее, они являются оригинальные массивы вместо ломтиков. Итак, если что-то добавлено к локальному массиву или если оно переназначено, это повлияет на исходный массив (тогда как это не было бы, если бы вы не использовали ref
).
Кроме того, ref
принимает только значения lvalues (значения, которые могут идти в левой части задания), а литералы массива являются значениями rvalues (что означает, что они могут идти только в правой части задания), поэтому вы не можете передать их функции, которая принимает свой аргумент ref
.Если вы хотите принять оба варианта, вам либо не нужно принимать ref
, перегрузите свою функцию, чтобы иметь версию ref
и не ref
(что похоже на то, что вы использовали в качестве своего решения), либо используйте auto ref
вместо ref
, и в этом случае он будет принимать оба (но auto ref
работает только с шаблонами функций, и это в основном просто короткая рука для дублирования функции самостоятельно, потому что это то, что делает auto ref
). В общем, хотя, если вы не хотите мутировать оригинал, вы не должны проходить мимо ref
.
Одно предложение сделать код быстрее: нет причин для , а затем снова переверните его и добавьте его вместе с b
. Если это то, что вы хотите сделать, вы можете также просто использовать только +=
и сделать что-то больше похоже на
T[] add(T)(T[] a, T[] b)
{
assert(a.length == b.length);
auto res = a.dup;
foreach (i; 0 .. a.length)
res[i] += b[i];
return res;
}
Или еще лучше, вы могли бы использовать array vector operations и пропустить цикл целиком:
T[] add(T)(T[] a, T[] b)
{
assert(a.length == b.length);
auto res = a.dup;
res[] += b[];
return res;
}
Но опять же, вы действительно должны прочитать http://dlang.org/d-array-article.html, если вы хотите правильно понять, как работают массивы в D.
не 'res [] + = b [];' также работает, чтобы исключить цикл? –
@ratchetfreak Это действительно работает, что было бы еще лучше. Я не очень хорошо разбираюсь в операциях с вектором массива, поэтому я не знаю точно, что вы можете и чего не можете с ними сделать. Я попробовал 'a [] + b []', который не работал и не сдавался. Но поскольку работает 'res + = b []', я буду соответствующим образом обновлять свой ответ. –