Jump to content

How to avoid copying arrays?


jasty
 Share

Recommended Posts

In every other language doing   

dim $a[3] = [1, 2, 3]

$b = $a

creates a reference to a but in autoit it always makes a copy.  I didn't realize this until I have performance problems and now I'm trying to switch over to the reference behavior.  How can I change the above statement so b is a reference to a and not a full copy? 

Edited by jasty
Link to comment
Share on other sites

  • Moderators

jasty,

If you are looking to pass the array as a parameter to a function, AutoIt does not make a copy of the array unless you alter the array in some fashion - even then you should be able to use ByRef to prevent this. Can you explain in more detail just what you are trying to do?

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

The help file (topic Func) should really be written as Melba23 just explained :

MB23 : " If you are looking to pass the array as a parameter to a function, AutoIt does not make a copy of the array unless ..."

Help file : "Arrays should be passed to user-defined functions using the ByRef keyword to avoid the overhead of copying all the data in the array."

* When you read this sentence in the help file, your 1st impression is that, without the ByRef keyword, the Array will be copied in the Function. The next sentences in the help file indicate you that it it's not always the case.

* When you read MB23 here, you understand immediately that, without the ByRef keyword, the Array will not be copied in the Function, unless...

I prefer MB23's explanation :)

Edited by pixelsearch
Link to comment
Share on other sites

  • Moderators

pixelsearch,

I believe the Help file text should remain as it currently reads - there is no guarantee that future AutoIt releases will retain the "no copy unless altered" functionality and so the user is best advised to pass arrays ByRef in all cases, as the Help file recommends (for precisely this reason).

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

Good to know, thx MB23

In fact, I was a bit perplexed about this "no copy unless altered" because it seems to be a functionality added to help the programmer, in case he forgot to use the ByRef keyword, to avoid a copy of the Array to be automatically done : this is how AutoIt reacts right now, to "avoid  copying all the data [Array in our case], which would impose a significant performance penalty"

If this functionality disappears in future AutoIt releases, programmers will have to be more careful : forgetting the ByRef Keyword will automatically do a copy of the Array (if I understood you well)

Edited by pixelsearch
Link to comment
Share on other sites

23 minutes ago, jasty said:

In the above code is $a actually copied?

Hi jasty :)

It sure is, as stated in the help file (topic Global/Local) :
"A unique feature in AutoIt is the ability to copy arrays like this:
$mycopy = $myarray
In this case $mycopy will be an exact copy of $myarray and will have the same dimensions"

As Melba23 wrote, the only case where it won't be copied is if you use the Array as a parameter in a function, using the keyword ByRef . Then the Array in the function won't be a copy of the original one.

In case it's not your need, please indicate why you need an array refering to another one, outside a function ?
Maybe It would help readers to provide a solution :)

 

Link to comment
Share on other sites

What about something like this...   does the array get copied after I retrieve it?

Func MyFunc($val, $arraytype)
    if $arraytype == 0 then
        $array = RetrieveDataOfSomeKind()
    else
        $array = RetrieveDataOfSomeOtherKind()
    endif
    $result = DoSomeAction($val, $array)
    Return $result
EndFunc

After coming from other languages I've never considered the assignment operator to be expensive.  

Link to comment
Share on other sites

@jasty

Yes, the retrieved elements of the array are copied into $array
Here is a script that could match partially your function (at least, this is how I understood it)

#include <Array.au3>
#include <MsgBoxConstants.au3>

Global $aBig_array[10] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
_ArrayDisplay($aBig_array, "$aBig_array - in main")
Test()

Func Test()
    $array = RetrieveDataOfSomeKind() ; an Array should be returned to populate $array
    _ArrayDisplay($array, "$array - in test()")
    If @error = 1 Then
        MsgBox($MB_TOPMOST, "Error", "$array is not an array")
    EndIf
EndFunc

Func RetrieveDataOfSomeKind()
    Local $aSmall_array[2]
    $aSmall_array[0] = $aBig_array[2]
    $aSmall_array[1] = $aBig_array[4]
    Return $aSmall_array
EndFunc

What Melba23 did explain concerned the ByRef keyword, for instance :

#include <Array.au3>

Global $aBig_array[10] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
_ArrayDisplay($aBig_array, "In main - before test()")
Test($aBig_array)
_ArrayDisplay($aBig_array, "In main - after test()")

Func Test(ByRef $array)
    ; $aBig_array[] hasn't been copied in the function, because of ByRef keyword
    ; and it will never be copied, even if you alter an element of $array.
    ;
    ; Now, notice how altering an element of $array will modify the original $aBig_array
    $array[9] = 999999999
    _ArrayDisplay($array, "$array - In test")
EndFunc

Same without ByRef (use it only if you really need a copy of the whole array in the function)

#include <Array.au3>

Global $aBig_array[10] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
_ArrayDisplay($aBig_array, "In main - before test()")
Test($aBig_array)
_ArrayDisplay($aBig_array, "In main - after test()")

Func Test($array)
    ; $aBig_array[] hasn't been copied in the function, BUT :
    ; it will be copied, as soon as you alter any element of $array !
    ; This functionality may eventually be removed in next AutoIt releases,
    ; so scripters will have to be extra careful concerning the ByRef keyword.
    ; The only case ByRef shouldn't be used is if you *really* need a copy of the array, here.
    ;
    ; Now, notice how altering an element of $array will NOT modify the original ($aBig_array)
    $array[9] = 999999999
    _ArrayDisplay($array, "$array - In test")
EndFunc

One more thing : Const ByRef (or ByRef Const) is even better, in case you don't want at all to modify the original array. It's an extra protection for scripters : an error will be generated if you modify any element inadvertly during the function :

Global $aBig_array[10] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Test($aBig_array)

Func Test(ByRef Const $array)
    ; Notice how altering inadvertly an element of $array will generate an error : thanks Const !
    $array[9] = 999999999
EndFunc

; Console shows the error :
; " Cannot assign values to constants "
; $array[9] = 999999999
; ^ ERROR

Good luck :)

Edited by pixelsearch
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...