www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Array-initialization

reply Hendrik Renken <funsheep gmx.net> writes:
Hi,

i have a question regarding array-initialization.


consider:

struct STRUCT
{
     byte[] data;
}


STRUCT foo(byte[] myData)
{
     STRUCT* s = new STRUCT(myData);
}


do i now create a struct with an array on the heap and then drop the 
array and assign to the array-pointer the array "myData"? If yes, how 
can i avoid the creation and deletion of the array "data" in the first 
place? Am i right, that the variable "data" only holds a pointer to the 
real array?

regards,
hendrik
Oct 09 2008
parent reply torhu <no spam.invalid> writes:
Hendrik Renken wrote:
 Hi,
 
 i have a question regarding array-initialization.
 
 
 consider:
 
 struct STRUCT
 {
      byte[] data;
 }
 
 
 STRUCT foo(byte[] myData)
 {
      STRUCT* s = new STRUCT(myData);
 }
 
 
 do i now create a struct with an array on the heap and then drop the 
 array and assign to the array-pointer the array "myData"? If yes, how 
 can i avoid the creation and deletion of the array "data" in the first 
 place? Am i right, that the variable "data" only holds a pointer to the 
 real array?
"data" is a dynamic array reference, so STRUCT is really just this: struct STRUCT { size_t length; byte* ptr; } So "data" is just a number of elements and a pointer to the first one. When you do "new STRUCT(myData)", you're only allocating room for that. There's no room for array contents allocated, just the reference. If you do writeln(STRUCT.sizeof); it will always say 8 on a 32-bit system, same goes for data.sizeof. Your example should probably look like this, as there's no point in heap allocating small structs: STRUCT foo(byte[] myData) { STRUCT s = STRUCT(myData); }
Oct 09 2008
parent reply Hendrik Renken <funsheep gmx.net> writes:
 "data" is a dynamic array reference, so STRUCT is really just this:
 
 struct STRUCT
 {
   size_t length;
   byte* ptr;
 }
This explains everything. Thanks.
  So "data" is just a number of elements and a pointer to the first one.
 When you do "new STRUCT(myData)", you're only allocating room for that. 
  There's no room for array contents  allocated, just the reference.
 
 If you do writeln(STRUCT.sizeof); it will always say 8 on a 32-bit 
 system, same goes for data.sizeof.
 
 
let me modify your example:
 STRUCT foo(byte[] myData)
 {
      STRUCT s = STRUCT(myData);
return s;
 }
will the content of s now be copied when it is returned?
 Your example should probably look like this, as there's no point in heap
 allocating small structs:
what means small? below how many bytes?
Oct 10 2008
next sibling parent "Jarrett Billingsley" <jarrett.billingsley gmail.com> writes:
On Fri, Oct 10, 2008 at 4:42 AM, Hendrik Renken <funsheep gmx.net> wrote:

 let me modify your example:

 STRUCT foo(byte[] myData)
 {
     STRUCT s = STRUCT(myData);
return s;
 }
will the content of s now be copied when it is returned?
Yes, the contents of *s* will be copied (that is, the array reference), but *not* the array data itself.
 Your example should probably look like this, as there's no point in heap
 allocating small structs:
what means small? below how many bytes?
It's subjective, but a struct that's only 4-8 bytes can be easily passed around in registers and there is therefore no need to heap-allocate it. Of course on a 64-bit platform even a 16-byte struct is small.
Oct 10 2008
prev sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
"Hendrik Renken" wrote
 "data" is a dynamic array reference, so STRUCT is really just this:

 struct STRUCT
 {
   size_t length;
   byte* ptr;
 }
This explains everything. Thanks.
  So "data" is just a number of elements and a pointer to the first one.
 When you do "new STRUCT(myData)", you're only allocating room for that. 
 There's no room for array contents  allocated, just the reference.

 If you do writeln(STRUCT.sizeof); it will always say 8 on a 32-bit 
 system, same goes for data.sizeof.
let me modify your example:
 STRUCT foo(byte[] myData)
 {
      STRUCT s = STRUCT(myData);
return s;
 }
will the content of s now be copied when it is returned?
the pointer will be copied. If you want a copy of the data, try this: STRUCT s = STRUCT(myData.dup); This duplicates the data before setting the pointer. array.dup is a shallow copy, so if you are duping an array of pointers, only the pointers get copied, not the data they point to. If you want a 'deep' copy, you have to loop and do it yourself at this point.
 Your example should probably look like this, as there's no point in heap
 allocating small structs:
what means small? below how many bytes?
All heap allocations are a minimum of 16 bytes. So if you are allocating a struct that just contains a pointer and a length (i.e. an array), that is an 8-byte struct on a 32 bit system. That means 100% overhead... Plus heap allocations require grabbing a global thread mutex, finding a suitable allocation block, possibly running a garbage collect cycle. They are slow, much slower than using a stack allocated struct. Of course if you are copying the data, a dup is going to do a heap allocation, so not much is gained by putting your struct on the stack. However, you probably don't *need* to use the heap for the struct data, I'd recommend against it. -Steve
Oct 10 2008