Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is this a valid use of an Objective-C pointer?

This is a beginner level question in which I'm curious if this is a valid use of a pointer in a statement such as:

 NSMutableDictionary *foo = [bar mutableCopy];

I get confused when that is valid versus when I'd need to do the following:

NSMutableDictionary *foo = [[NSMutableDictionary alloc] initWithCapacity:0];
foo = [bar mutableCopy];
// use foo
[foo release];

Are both valid? When to use one over the other?

like image 283
Coocoo4Cocoa Avatar asked Mar 20 '09 21:03

Coocoo4Cocoa


4 Answers

Guessing at why you might be confused, I'd like to add an explanation of what the second code sample actually does (and why it's not necessary).

NSMutableDictionary *foo = [[NSMutableDictionary alloc] initWithCapacity:0];

I think you are getting confused by this line because this line is often described as "initializing foo". That's a bit misleading. There are technically 2 different entities being changed here -- the new NSMutableDictionary object is created and the "foo" variable is assigned its address.

The line actually creates a new NSMutableDictionary object on the heap (your application's dynamic memory area). I'll call this "Dictionary 1". So that this new "Dictionary 1" object on the heap can be found, its memory address is stored in "foo". "foo"s role is to act as an index, so we can find "Dictionary 1".

While we often say: "foo is a dictionary", that's because we are lazy -- the statement is technically wrong. Correctly: "there is a dictionary on the heap and foo stores its memory address so that we can find it and use it".

When you then run the line:

foo = [bar mutableCopy];

you are using the address in "bar" to find a different object (I'll call it "Dictionary 2") in the heap, and make yet another object ("Dictionary 3") on the heap with the same values. If you're keeping count, this is now 3 objects in existence.

After "Dictionary 3" is made, its memory address is then stored in the "foo" variable. This storing into "foo" overwrites the existing memory address (the one that pointed to "Dictionary 1"). This means that we have no remaining pointers to "Dictionary 1" and hence will never be able to find it again. This is why we say "Dictionary 1" has leaked.

I hope you can see from this situation why "Dictionary 1" was never needed (you only ever intended to use "foo" to access the copy, "Dictionary 3").

like image 149
Matt Gallagher Avatar answered Oct 18 '22 06:10

Matt Gallagher


You would never need to write the code in the second example. The [[NSMutableDictionary alloc] initWithCapacity:0] does nothing except leak memory.

In the second example, you create an NSMutableDictionary and assign it to foo. Then in the next line, you assign a copy of another NSMutableDictionary to foo, meaning that the original dictionary foo pointed to is now just floating off somewhere on the heap, unable to ever be freed.

You will need to release foo in either case, though, as laid out in the Objective-C memory management guidelines.

like image 29
Chuck Avatar answered Oct 18 '22 05:10

Chuck


The first one is correct, the second leaks memory because you alloc twice (copy counts as one) and release only once.

Don't forget to release foo after you are done though

like image 31
cobbal Avatar answered Oct 18 '22 05:10

cobbal


The act of assignment overwrites the previous value held by that variable. For example:

x = 3
x = 4

The value held by x at the start of the second line is 3, but after the line of code executes, it is 4. The syntax:

int x = 0;

is really just shorthand for this:

int x;
x = 0;

Variables that are pointers are no different. Thus if the variable's first reference is simply to assign to it, you do not need to first initialize it, because whatever value you're initializing it with will simply be discarded.

like image 27
Ecton Avatar answered Oct 18 '22 05:10

Ecton