2016-01-18 6 views
4

Я пришел из мира C# и используется для массивов, являющихся ссылочными типами. Насколько я понимаю, в быстрых массивах есть типы значений, но они пытаются играть как контрольные.Локальная ссылка на внутренний массив в swift

Я действительно не знаю, как спросить, что мне нужно (я думаю, что это тот случай, когда мне нужно знать ответ, чтобы задать вопрос), но в C# я бы сказал, что мне нужно сохранить ссылку на Внутренний массив неровного массива в локальную переменную.

Рассмотрим следующий фрагмент кода:

// a function to change row values in-place 
func processRow(inout row : [Int], _ value : Int) 
{ 
    for col in 0..<row.count 
    { 
     row[col] = value; 
    } 
} 

// a function to change matrix values in-place 
func processMatrix(inout matrix : [[Int]]) 
{ 
    for rowIdx in 0..<matrix.count 
    { 
     // (1) Works with array in-place 
     processRow(&(matrix[rowIdx]), -1) 

     // (2) Creates local copy 
     var r = matrix[rowIdx]; // <--- What to write here to not make a copy but still have this local variable? 
     processRow(&r, -2); 
    } 
} 

var matrix = [ 
    [1, 2, 3], 
    [4, 5, 6], 
    [7, 8, 9] 
] 

processMatrix(&matrix) 

print(matrix) // outputs [[-1, -1, -1], [-1, -1, -1], [-1, -1, -1]] 

Swift песочнице здесь http://swiftlang.ng.bluemix.net/#/repl/8608824e18317e19b32113e1aa08deeb4ec5ab96ed8cdbe1dbfb4e753e87d528

Здесь я хочу обрабатываю многомерный массив на месте, так что я не создавать копию массива или части массива.

В опции (1) я меняю все на «-1», и он работает, но для этого используется дополнительная функция.

В опции (2) Я пытаюсь использовать локальную переменную для хранения matrix[rowIdx], но на самом деле она создает копию внутреннего массива - не то, что я хочу; работа с этой переменной меняет копию массива, а не оригинальную.

Как достичь результатов, как в опции (1), но используя локальную переменную вместо функции? То есть, как я могу получить ссылку на внутренний массив и поместить его в локальную переменную?

Я понял бы, что «нет никакого способа для этого», но я хочу, чтобы такие ответы сопровождались некоторыми комментариями от Apple.

ответ

1

Я не верю, что есть способ скопировать массив в локальную переменную без создания копии. Это то, как работают типы значений в Swift. Says Apple:

Самого основная отличительная черта типа значения является то, что копирование - эффект присвоения, инициализации и передачи аргументов - создает независимый экземпляр с его собственной уникальной копией его данными

[.]

And here:

Тип значения является тип, значение копируется при присваивании переменной или константой, или когда оно передается функции ...

[...]

Все структуры и перечисления являются типами значений в Swift. Это означает, что любые созданные вами экземпляры структуры и перечисления, а также любые типы значений, которые они имеют в качестве свойств, всегда копируются, когда они передаются в вашем коде.

Это просто часть определения типа значения - и каждый массив является типом значения.

Самый простой способ, чтобы получить результат, который Вы ищете просто переназначить значение r к строке, которую вы хотите изменить в matrix:

// (2) Creates local copy 
var r = matrix[rowIdx] 
processRow(&r, -2) 
matrix[rowIdx] = r 

Ближе всего к тому, что вы предлагаете, чтобы работа с указателями: UnsafeMutablePointer, UnsafePointer и т. д.Но это действительно борьба с тем, как Swift был разработан для использования. Если вы хотите, однако, это будет выглядеть примерно так:

func processRow(ptr: UnsafeMutablePointer<Int>, _ value : Int, count: Int) { 
    for col in 0..<count { 
     ptr.advancedBy(col).memory = value 
    } 
} 

func processMatrix(inout matrix : [[Int]]) { 
    for rowIdx in 0..<matrix.count { 

     let r = UnsafeMutablePointer<Int>(matrix[rowIdx]) 
     processRow(r, -2, count: matrix[rowIdx].count) 
    } 
} 

var matrix = [ 
    [1, 2, 3], 
    [4, 5, 6], 
    [7, 8, 9] 
] 

processMatrix(&matrix) 
print(matrix) // [[2, 2, 2], [2, 2, 2], [2, 2, 2]] 
+0

Спасибо вам ответить 1) Массивы являются «специальные» типы значений, поэтому экстракты вы цитируете в основном неправильно для массивов. Например, эта функция «копировать-на-запись», как показано здесь, http://swiftlang.ng.bluemix.net/#/repl/f3dff0253eefbc2c86abc52e5f224210fe097c589bad1e8cbdd381c1eb61b9e9 показывает, что массивы не всегда копируются при их передаче вокруг 2) Копирование матрицы [rowIdx] = r' - это то, что я пытаюсь избежать - я хочу всегда работать с массивом на месте 3) 'UnsafeMutablePointer' близок, но поскольку это * небезопасный * и * указатель *, он поднимает старую хорошую C указатель ад, но я буду играть больше с ними – Lanorkin

+0

Справедливые баллы. 1) Массивы не * это * специальные. Копия на поведение записи полностью «под капотом». Невозможно взаимодействовать с ними, кроме как типов значений (указатели в сторону). 2) Почему не 'matrix [rowIdx] = [2, 2, 2]'? Возможно, вы делаете это более сложным, чем нужно. 3) Да, 'UnsafeMutablePointer' небезопасен и указатель. Я думаю, что Apple отговаривает их использовать, дав им страшное имя. Но они - единственный инструмент (AFAIK) для того, чтобы делать то, что вы хотите. Большая картина, позволяющая типам значений вести себя как ссылочные типы, подрывает всю точку со значениями типов. –

+0

Я думаю, что указатель ближе всего к ссылке на локальный массив здесь, но единственное * пригодное для использования * решение, которое я вижу, это пойти с отдельным методом 'func (inout ...)' для каждой локальной переменной, которая мне нужна для массива. Я чувствую себя неуверенным, разочарованным и подавленным, но принимаю. – Lanorkin

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

  • Нет связанных вопросов^_^