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?
-
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.yves Baumes : "&objs[0] is guaranteed to point to a contiguous sequence in memory" But please be warnd: that's only ok when you are sure your vector is not empty (using empty() method for instance). Otherwise it could lead to Undefined behavior.Judge Maygarden : That's true and noted.aJ : if you know size in advance then Vector::reserve() would be helpful. -
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.
jalf : 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. -
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];
Tjofras : it should be, MyObject* objs = new MyObject[size]; right?Mel Green : oh, I think you're correct. I've gotten so used to C# it's tainted my C++ :) -
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.
-
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.
-
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 as2[a]
: i.e., the third element ina
(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 withstd::vector
makes even more sense (because you don't have to remember to calldelete[]
every place the array goes out of scope due to return, break, the end of statement, throwing an exception, etc.). -
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.
-
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 thatarr
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.
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.