Что нового

[Массивы] Массив как элемент массива

iltmpz

Новичок
Сообщения
23
Репутация
0
Приветствую!
Не совсем понимаю синтаксис и механизм работы с массивами в autoit.

Конкретный вопрос: Хочу хранить несколько списков процессов получаемых ProcessList()
Хотел сделать вот так:
Код:
Global $aProcessLists[10]
$aProcessLists[0]=ProcessList()
Sleep(1000)
$aProcessLists[1]=ProcessList()
; и т.д...

Т.е. по моей задумке, $aProcessLists будет 3-мерным массивом, элементами которого становятся 2-мерные массивы, возвращаемые ProcessList()
Однако, на попытку прочитать $aProcessLists[0][0][0] AutoIt ругается:
"Array variable has incorrect number of subscripts or subscript dimension range exceeded."
Почему?
Я не могу записать содержимое массива в качестве элемента массива? А как быть?
Делать присваивание поэлементно с помощью 2 вложенных циклов? Будет медленно и громоздко.
Может быть, есть какой-то синтаксический трюк?

2-й вопрос, про механизм работы: если я присваиваю результат выполнения функции, являющийся массивом некой переменной, происходит копирование данных или присваивание ссылки?
3-й вопрос, в какой момент произойдет освобождение памяти от данных массива?
Допустим, код:
Код:
Func TestProcessList()
 Local $aProcessList
 $aProcessList=ProcessList()
 Sleep(1000)
 $aProcessList=ProcessList()
EndFunc

Правильно ли я понимаю:
1. Когда переменная aProcessList заканчивает свою жизнь, т.е. при завершении функции, в которой она была локальной, происходит фактическое удаление данных, которые в нее писались?
2. Когда переменной происходит присваивание, а в ней уже что-то было, это "что-то" удаляется, память освобождается?
 
Автор
I

iltmpz

Новичок
Сообщения
23
Репутация
0
iltmpz сказал(а):
Однако, на попытку прочитать $aProcessLists[0][0][0] AutoIt ругается:
"Array variable has incorrect number of subscripts or subscript dimension range exceeded."
Почему?
Я не могу записать содержимое массива в качестве элемента массива? А как быть?
Делать присваивание поэлементно с помощью 2 вложенных циклов? Будет медленно и громоздко.
Может быть, есть какой-то синтаксический трюк?
Вроде, придумал трюк:
$aProcessLists[$i] передаю в функцию через ByRef:
Код:
For $i=0 To 9
; в функцию передаем каждый элемент массива, который сам по себе является 2-мерным массивом
 FuncProcess($aProcessLists[$i])
 Sleep(1000)
Next
; тогда уже в функциии эта переменная - сама по себе - 2-мерный массив. А передача ByRef означает, что никаких лишних переприсваиваний массивов не будет.
Func FuncProcess(ByRef $aProcessList)
 For $i=1 To $aProcessList[0][0]
  ; работаем как с обычным 2-мерным массивом
 Next
EndFunc


А вот что касается механизма работы с массивами в AutoIt - вопрос остается в силе.
А то разбаловался C/C++, где все понятно - либо передаешь массив по ссылке, либо явно выделяешь память, копируешь, удаляешь, освобождаешь, ну либо неявно через конструктор копирования.
А вот как это устроено в AutoIt - не понимаю, а хочется понимать.
 

joiner

Модератор
Локальный модератор
Сообщения
3,557
Репутация
628
как это понял я :smile:
Код:
#include <Array.au3>
Local $Array1[3] = [0, 1, 2]
Local $Array2[3] = [3, 4, 5]
Local $Arrays[1][2]
$Arrays[0][0] = $Array1
$Arrays[0][1] = $Array2

_aRF($Arrays)
_ArrayDisplay($Arrays[0][0])
_aRF($Arrays, 1)
_ArrayDisplay($Arrays[0][1])

Func _aRF(ByRef $Array, $Ind = 0)
	Local $aGT = $Array[0][$Ind]
	$aGT[1] = Random(15, 155, 1)
	$Array[0][$Ind] = $aGT
EndFunc   ;==>_aRF
 

InnI

AutoIT Гуру
Сообщения
4,958
Репутация
1,448
iltmpz
Может быть, есть какой-то синтаксический трюк?
Да есть. Скобки нужны. Но это только для чтения, для записи не получится
Код:
Global $aProcessLists[10]
$aProcessLists[0]=ProcessList()
Sleep(1000)
$aProcessLists[1]=ProcessList()

$iCount = ($aProcessLists[0])[0][0]
ConsoleWrite($iCount & @CRLF)
$iCount = ($aProcessLists[1])[0][0]
ConsoleWrite($iCount & @CRLF)


как это устроено в AutoIt - не понимаю, а хочется понимать
Насколько я понимаю ;) всё устроено неоднозначно. Похоже, что массивы копируются только при необходимости, т.е. когда массив нужно изменять. Вот небольшой пример, грубо показывающий расход памяти процессом при разных операциях с массивами (массив создаётся около 10 секунд). Но даже при таком грубом подходе становится понятно, где происходит копирование, а где нет
Код:
ShowMem("Старт")

Global $a[1e7]
For $i = 0 To UBound($a) - 1
  $a[$i] = $i
Next
ShowMem("Заполнили массив")

$c = $a
ShowMem("Скопировали массив")

$c[1000] = 1
ShowMem("Изменили массив")

$c = "string"
ShowMem("Удалили массив")

$v = Test($a)
ShowMem("Вернулись из функции")

$v = 0
ShowMem("Удалили массив")

Func Test($ar)
  Local $b = $a
  ShowMem("Скопировали массив")
  $ar[1000] = 1
  ShowMem("Изменили копию массива")
  Return $ar
EndFunc

Func ShowMem($s)
  Local Static $p = 0
  Local $m = ProcessGetStats()[0]
  Local $d = Round(($m - $p) / 1e6, 1)
  MsgBox(0, $s, $d >= 0 ? "+" & $d : $d)
  $p = $m
EndFunc

И попробуйте поиск по форуму по фразе "массив массивов" - много уже обсуждали.
 
Верх