views:

213

answers:

8

I have been given a header with the following declaration:

//The index of 1 is used to make sure this is an array.
MyObject objs[1];

However, I need to make this array dynamically sized one the program is started. I would think I should just declare it as MyObject *objs;, but I figure if the original programmer declared it this way, there is some reason for it.

Is there anyway I can dynamically resize this? Or should I just change it to a pointer and then malloc() it?

Could I use some the new keyword somehow to do this?

+17  A: 

Use an STL vector:

#include <vector>

std::vector<MyObject> objs(size);

A vector is a dynamic array and is a part of the Standard Template Library. It resizes automatically as you push back objects into the array and can be accessed like a normal C array with the [] operator. Also, &objs[0] is guaranteed to point to a contiguous sequence in memory -- unlike a list -- if the container is not empty.

Judge Maygarden
yves Baumes
That's true and noted.
Judge Maygarden
if you know size in advance then Vector::reserve() would be helpful.
aJ
A: 

Using the STL is best if you want a dynamically sizing array, there are several options, one is std::vector. If you aren't bothered about inserting, you can also use std::list.

Mark Ingram
That doesn't solve his problem. If he can change it to a pointer, he has plenty of options for resizing it. realloc won't let him resize the array while using the current declaration.
jalf
+5  A: 

You're correct. If you want to dynamically instantiate its size you need to use a pointer.

(Since you're using C++ why not use the new operator instead of malloc?)

MyObject* objs = new MyObject[size];
Mel Green
it should be, MyObject* objs = new MyObject[size]; right?
Tjofras
oh, I think you're correct. I've gotten so used to C# it's tainted my C++ :)
Mel Green
A: 

Its seems - yes, you can do this change.
But check your code on sizeof( objs );

MyObj *arr1 = new MyObj[1];
MyObj arr2[1];

sizeof(arr1) != sizeof(arr2)

Maybe this fact used somewhere in your code.

bb
+3  A: 

Or should I just change it to a pointer and then malloc() it?

If you do that, how are constructors going to be called for the objects in on the malloc'd memory? I'll give you a hint - they won't be - you need to use a std::vector.

anon
A: 

That comment is incredibly bad. A one-element array is an array even though the comment suggests otherwise.

I've never seen anybody try to enforce "is an array" this way. The array syntax is largely syntactic sugar (a[2] gives the same result as 2[a]: i.e., the third element in a (NOTE this is an interesting and valid syntax but usually a very bad form to use because you're going to confuse programmers for no reason)).

Because the array syntax is largely syntactic sugar, switching to a pointer makes sense as well. But if you're going to do that, then going with new[] makes more sense (because you get your constructors called for free), and going with std::vector makes even more sense (because you don't have to remember to call delete[] every place the array goes out of scope due to return, break, the end of statement, throwing an exception, etc.).

Max Lybbert
+1  A: 

I have only seen an array used as a pointer inside a struct or union. This was ages ago and was used to treat the len and first char of a string as a hash to improve the speed of string comparisons for a scripting language.

The code was similar to this:

union small_string {
   struct {
      char len;
      char buff[1];
   };
   short hash;
};

Then small_string was initialised using malloc, note the c cast is effectively a reinterpret_cast

small_string str = (small_string) malloc(len + 1);
strcpy(str.buff, val);

And to test for equality

int fast_str_equal(small_string str1, small_string str2)
{
   if (str1.hash == str2.hash)
      return strcmp(str1.buff, str2.buff) == 0;
   return 0;
}

As you can see this is not a very portable or safe style of c++. But offered a great speed improvement for associative arrays indexed by short strings, which are the basis of most scripting languages.

I would probably avoid this style of c++ today.

iain
+1  A: 

Is this at the end of a struct somewhere?

One trick I've seen is to declare a struct

struct foo {
/* optional stuff here */
int arr[1];
}

and malloc more memory than sizeof (struct foo) so that arr becomes a variable-sized array.

This was fairly commonly used in C programs back when I was hacking C, since variable-sized arrays were not available, and doing an additional allocation was considered too error-prone.

The right thing to do, in almost all cases, is to change the array to an STL vector.

David Thornley