Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

Consider the following small script:

$a = @(1,2,3)         #1
$b = $a               #2
$a[0] = 101           #3
$b += 99              #4
Write-Host "a: $a"
Write-Host "b: $b"

The output is this which required me to think a bit:

a: 101 2 3 b: 101 2 3 99

My observations for clarification:

  1. The $b array contains four elements in the output so $b = $a is creating a copy of original array with three items in it and then the 99 element is added. If $b = $a was a pointer operation, then adding an element to $b would effect the $a array as well
  2. The array contains pointers to the integers and not the integers themselves. Proved by the fact that line #3 changes the contents of both arrays. If $a contained integers, then $b wouldn't have been affected

So my understanding is:

A PowerShell array is always an array of pointers even if it contains just integers. Assigning an array to another variable creates a copy of that array of pointers.

Right?

share|improve this question

2 Answers 2

up vote 3 down vote accepted

I don't know the actual reason behind this, but if you look at this behavior, you can begin to understand it:

$a = @(1,2,3)
[int[]]$b = $a
$a[0] = 101
$b += 99

Write-Host $a"`n"
101 2 3

Write-Host $b"`n"
1 2 3 99

You can see that it does not "link" $b to $a and instead initializes it as a separate array.


Further reading on Value Types VS Reference Types

http://www.leeholmes.com/blog/2006/09/05/value-types-vs-reference-types/

http://kizan.com/20143263-reference-types-powershell/

share|improve this answer
    
Thanks for this addition as it does make it clear what's happening. For somebody coming from a more traditional C/VB background, it caught me out. I'm not saying PowerShell is wrong - just different. I suppose my next question should be can you work with references to arrays. In my real life example, I wasn't actually working with integers but a JSON tree structure and I assigned a variable to a collection part way down the tree expecting a pointer but got a copy of the array instead and then wondered why the changes weren't written back –  Rob Nicholson Feb 10 at 11:01
    
I think that the data types are pretty flexible in Powershell, to the point where it's not worth worrying about. Although I did dig up some articles that might help in terms of understanding. I've added them to my answer. –  Vasili Syrakis Feb 10 at 11:44

I think internally these are implemented as linked lists and not arrays. The difference being that it is very expensive to add an item to an array, because the size of an array is declared, then contiguous memory is allocated for it. Because of this, there is no guarantee that the next contiguous block of memory is available to the array, and a new array of size (origArray + 1) has to be created, the old array copied in and the new element copied in as well. I have no proof of this of course other than programming experience and observing the behavior of powershell.

Update

I do have proof! Avoiding the list operator vs. How an Array is declared in powershell. Note the user of the New-Object cmdlet when declaring an array:

PS > $myArray = New-Object string[] 10

So, what you're interacting with on the command line are two linked lists. I'm not sure how Powershell/.NET handles copying linked lists, although it appears from your example that for efficiency $b simply holds the same pointers as $a, but when you add an item to $b or $a it doesn't show up in the other, unless explicity copied again. I like to refer to this as a static copy, though I don't know if that term has use in the field.

share|improve this answer
    
Thinking further, it's preferable that the array contains pointers and not the actual variables. Just think of the performance overhead if large objects were being manipulated and not small integer. An operation like $a[0] = SomeBigObject would be pretty slow if it made a copy of the object. The gotcha for me coming from vb.net is that Array2 = Array1 is a pointer operation - it doesn't create a duplicate array which I'm pretty sure is what PowerShell is doing –  Rob Nicholson Feb 8 at 16:45

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.