3

I have a question regarding memory allocation for Objects in an array. I am looking to create an array of Objects, but at compile time, I have no way of knowing how many objects I will need, and thus don't want to reserve more memory than needed.

What I would like to do is allocate the memory as needed. The way I would like to do this is when the user clicks an "Add" button, the array is increased by one additional object and the needed memory for the new object is allocated.

In my novice understanding of Objective C (I was a professional programmer about 20 years ago, and have only recently begun to write code again) I have come up with the following code segments:

First, I declared my object:

    NSObject *myObject[1000]; // a maximum number of objects.

Then, when the user clicks an Add button it runs a method with the allocation code: (note: the variable i starts out at a value of 1 and is increased each time the Add button is clicked)

    ++i
    myObject[i] = [[NSObject alloc] init];

Thus, I'm hoping to only allocate the memory for the objects actually needed, rather than all 1000 array objects immediately.

Am I interpreting this correctly? In other words, am I correct in my interpretation that the number of arrayed elements stated in the declaration is the MAXIMUM possible number of array elements, not how much memory is allocated at that moment? It this is correct, then theoretically, the declaration:

    NSObject *myObject[10000];

Wouldn't pull any more memory than the declaration:

    NSObject *myObject[5];

Can someone confirm that I'm understanding this process correctly, enlighten me if I've got this mixed up in my mind. :)

Thanks!

Greg Steiner
  • 647
  • 1
  • 9
  • 20
  • Why don't you use an NSMutableArray or a CFMutableArray? It efficiently adds objects. Here's the source for CFArray, if you'd like to take a look: http://www.opensource.apple.com/source/CF/CF-635/CFArray.c – Jack Lawrence Apr 23 '12 at 03:11
  • Thanks for that tip. I'm sure that's probably the way I should do it. I hadn't heard of either of those until now. Curiously, although I know I'm probably re-inventing the wheel, in theory, is my understanding of memory allocation accurate? – Greg Steiner Apr 23 '12 at 03:14
  • Don't ever use C arrays of Objective-C objects, it's a bad idea. Use the array objects supplied by the language. I *highly* recommend you read an Objective-C book. The best one (IMHO) is [Programming In Objective-C](http://www.amazon.com/dp/0321811909/) by Stephen Kochan. – Rob Keniger Apr 23 '12 at 07:45
  • Plus you get *so* many useful methods/functions with CFArray/NSArray. With NSArray you can do fancy things like `-makeObjectsPerformSelector:` to have them all call a method, or Objective-C fast enumeration using blocks or with the `for ( * in ){// do stuff}` – Jack Lawrence Apr 23 '12 at 15:31
  • Rob - I have that particular Objective-C book and have been working through it. I just happened to be jumping ahead and experimenting as I go... sometimes that helps, othertimes it leads me in a completely wrong direction as in this case :) – Greg Steiner Apr 28 '12 at 20:24

2 Answers2

4

Why not use NSMutableArray? You can initWithCapacity or simply allocate with [NSMutableArray array]. It will grow and shrink as you add and remove objects. For example:

NSMutableArray *array = [NSMutableArray array];
NSObject *object = [[NSObject alloc] init];

[array addObject:object]; // array has one object
[array removeObjectAtIndex:0]; // array is back to 0 objects

// remember to relinquish ownership of your objects if you alloc them
// the NSMutable array was autoreleased but the NSObject was not
[object release]; 
Ben Harris
  • 5,664
  • 3
  • 30
  • 27
  • Check out the NSMutableArray and NSArray docs to see all the other cool functions they have. https://developer.apple.com/library/ios/#documentation/Cocoa/Reference/Foundation/Classes/NSMutableArray_Class/Reference/Reference.html – Ben Harris Apr 23 '12 at 03:17
  • NSArray releases all of its objects when it receives a call to dealloc. That's why if you have, for example, a synthesized property of type `NSArray`, you only have to release the NSArray in `-dealloc` and not its contents as well. – Jack Lawrence Apr 23 '12 at 15:34
  • @JackLawrence, that is correct, however calling alloc on an object increments its retain count by 1. Adding that object to the NSArray also increments its retain count to 2. Had I not called [object release] when I did, removing the object from the array would leave the objects retain count at 1 thus preventing the memory from being reclaimed by the system. – Ben Harris Apr 24 '12 at 02:19
3

Your understanding is mostly correct. When you do:

NSObject *myObject[1000];

You immediately allocate storage for 1000 pointers to NSObject instances. The NSObject instances themselves are not allocated until you do [[NSObject alloc] init].

However, doing NSObject *myObject[10000] will consume more space than doing NSObject *myObject[5], because 10,000 pointers certainly require more memory to represent than 5 pointers.

Remember that both things consume space, the pointer to the NSObject, and the NSObject instance itself, though in practice the space consumed by an NSObject instance will be significantly larger than the 4 bytes consumed by the pointer that refers to it.

Anyhow, perhaps more importantly, there is a better way to manage dynamic object allocation in Cocoa. Use the built-in NSMutableArray class. Like:

NSMutableArray* objects = [[NSMutableArray alloc] init];
[objects addObject: [[[NSObject alloc] init] autorelease]];
aroth
  • 54,026
  • 20
  • 135
  • 176
  • Excellent explanation. Thanks. I completely forgot about the fact that the pointers themselves were having memory allocated. In essence, the objects are basically a type of database record. an NS object containing a bunch of variables and a few methods. – Greg Steiner Apr 23 '12 at 03:21
  • Right now, I can access the variables in an object by using accessor methods, such as: x = [myObject var]; If I add myObject's into the array objects, is there a simple way to use the myObject's accessor methods? I'm sure it's something along the lines of: x = [[objects ] var]; – Greg Steiner Apr 23 '12 at 03:27
  • Yes, that's close. It's `x = [[objects objectAtIndex:] var]`. You may find the [reference docs](https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSMutableArray_Class/Reference/Reference.html) useful. – aroth Apr 23 '12 at 03:33