www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Arrays, copied or referenced?

reply Audun Wilhelmsen <seronor gmail.com> writes:
Hey..

Take this code: 
--------------------------
import std.stdio;

int[] arrayTest(int[] a) {
	a.length = 5;
	a[4] = 42;
	return a;
}

int main(char[][] args) {
	int[10] foobar;
	foobar[4] = 2;
	arrayTest(foobar);
	writefln("%d", foobar[4]);
        return 0;
}
--------------------------
It prints out "42".
Now replace the line "a.length = 20", and it prints out "2".

Is that the way it's supposed to behave?

Audun Wilhelmsen
NTNU, Norway
Aug 05 2007
next sibling parent BCS <ao pathlink.com> writes:
Reply to Audun,

 Hey..
 
 Take this code:
 --------------------------
 import std.stdio;
 int[] arrayTest(int[] a) {
 a.length = 5;
 a[4] = 42;
 return a;
 }
 int main(char[][] args) {
 int[10] foobar;
 foobar[4] = 2;
 arrayTest(foobar);
 writefln("%d", foobar[4]);
 return 0;
 }
 --------------------------
 It prints out "42".
 Now replace the line "a.length = 20", and it prints out "2".
 Is that the way it's supposed to behave?
 
 Audun Wilhelmsen
 NTNU, Norway
The assignment to length forces a reallocation of the array, Until then 'a' is a reference of the data from the parent. After that you have a reference to a new array.
Aug 05 2007
prev sibling parent Kirk McDonald <kirklin.mcdonald gmail.com> writes:
Audun Wilhelmsen wrote:
 Hey..
 
 Take this code: 
 --------------------------
 import std.stdio;
 
 int[] arrayTest(int[] a) {
 	a.length = 5;
 	a[4] = 42;
 	return a;
 }
 
 int main(char[][] args) {
 	int[10] foobar;
 	foobar[4] = 2;
 	arrayTest(foobar);
 	writefln("%d", foobar[4]);
         return 0;
 }
 --------------------------
 It prints out "42".
 Now replace the line "a.length = 20", and it prints out "2".
 
 Is that the way it's supposed to behave?
 
 Audun Wilhelmsen
 NTNU, Norway
I've set the Followup-To to digitalmars.D.learn. This is perhaps a tricky subject. The answer is yes, that is the correct behavior. Let me copy your function again: int[] arrayTest(int[] a) { a.length = 5; a[4] = 42; return a; } Dynamic arrays in D are a struct that looks something like this: struct dyn_array { void* ptr; size_t length; } When you pass an array to arrayTest, it passes this struct by value. When you say: a.length = 5; There is some logic that it does behind the scenes. If the new length is shorter than the old length, it simply changes the length attribute of the struct, and the pointer refers to the same chunk of memory that it did before. If the new length is longer than the chunk of memory to which ptr points (which in this example is a static array in main, so this is always true if you make the length longer), it will allocate a new array on the heap, and copy the array contents into it. Thus, when you say 'a.length = 20', you're suddenly referring to a different chunk of memory. This allocation is not always guaranteed to happen, which is why I said this is a tricky subject. To get actual reference semantics, you should use something like this: void arrayTest(ref int[] a) { a.length = 20; a[4] = 42; } void main() { int[] foobar = new int[](10); foobar[4] = 2; arrayTest(foobar); writefln("%d", foobar[4]); } Note the 'ref' in arrayTest's parameter. Also note that it's passing an int[] and not an int[10] to arrayTest: You can't assign a dynamic array to a static array. However, if you're just passing the contents of the array to a function, and not modifying the array itself, passing a regular int[] will get you all of the reference semantics you need. -- Kirk McDonald http://kirkmcdonald.blogspot.com Pyd: Connecting D and Python http://pyd.dsource.org
Aug 05 2007