c++ equivalent in Objective-C [alloc [init]] - objective-c

Am I right in saying the equivalent of:
NSMutableArray *foo;
foo = [[NSMutableArray alloc] init];
[foo release];
Is C++:
NSMutableArray *foo = new NSMutableArray();
delete foo;
ie. The 2nd line of the Obj-C does the dynamic memory allocation, while first just makes a pointer? In this case, what is the function of [init] VS. [alloc]?
thanks guys - I'm almost finding a bit of C++ is almost a hindrance to learning Obj-C!

Internally C++ can be doing something very similar to alloc+init. In this case alloc does the actual memory allocation (the new), and init acts more or less as your constructor.

alloc is the equivalent of new() and init is the equivalent of a C++ object constructor.

I think the nearest C++ equivalent to Objective-C's two-stage alloc/init would be to call malloc to allocate a buffer, then use placement new to call the constructor for the previously-allocated memory block:
void *buffer = malloc(sizeof(NSMutableCPPArray));
NSMutableCPPArray *foo = new(buffer) NSMutableCPPArray();
In this example, the first line corresponds to alloc, dynamically allocating a new memory block for the object to use. The second line is similar to init, calling the constructor to initialize that memory block.
Of course, one key difference is that Objective-C's alloc/init pair is a fundamental and widely-used part of the standard Foundation library. Placement new, by contrast, is an odd and rarely-used corner of C++ that is loaded with caveats and warnings in the online C++ FAQ.

In addition to the basic semantic of the code you have showed, you have to consider the way memory is handled by the given programming languages. In Objective-C each object has a retain-count which is used when release is called (and an object needs a retain count of 0 before deletion). In C++ there is no such mechanism, and you have to handle memory all by your self when using new and delete (which can have memory leaks).
If you want memory management ala Objective-C you should check out the header of C++0x which includes the shared_ptr object (which behaves more alike Objective-C).

Related

Release allocated or initialized object in objective-c?

Memory management says we must release an object created with alloc. Consider this typical example code.
XYZClass *obj = [[XYZClass alloc] init];
// use obj
[obj release];
But in this example, obj may not be the object returned from alloc, as Apple's documentation says
Note: It’s possible for init to return a different object than was created by alloc, so it’s best practice to nest the calls as shown.
So this typical example seems to release the object returned from init, breaking memory management rules, and not release the object returned from alloc, further breaking the rules.
How is this typical example valid?
First of all you code uses manual memory management, that is something I would not recommend, since Xcode 4.2 for OS X v10.6 and v10.7 (64-bit applications) and for iOS 4 and iOS we have support for Automatic Reference Counting (ARC) is a compiler feature that provides automatic memory management of Objective-C objects. See Transitioning to ARC Release Notes :
Instead of your having to remember when to use retain, release, and
autorelease, ARC evaluates the lifetime requirements of your objects
and automatically inserts appropriate memory management calls for you
at compile time. The compiler also generates appropriate dealloc
methods for you.
With regards to your specific question, the fact that init might return a different object does not break the memory management, because that different object will use the same allocation. This is quite common for class clusters that the initializer might return a internal subclass.

Releasing an object from ARC method which calls a no-arc C function

I'm using a library that is not ARC compliant from an ARC based project. A function in that library returns a retained UIImage * object. Is there a way to use the __bridge attributes to let ARC know about this so it can manage the retain count of the returned object? I tried:
UIImage *returnedImage;
returnedImage = (__bridge_transfer UIImage *)functionThatReturnsAUIImage();
But it won't allow me to cast the UIImage * to a UIImage *). I also tried:
returnedImage = (UIImage *)(__bridge_transfer void *)functionThatReturnsAUIImage();
Which also didn't work. The compiler suggested __bridge_retained instead of __bridge_transfer, but that I believe would have done the opposite of what I was after (i.e. it would have increased the retain count on the returned UIImage object).
I believe the proper thing to do is to make the C function return an autoreleased object. As best as I can tell, ARC assumes any C function that returns an object will have returned an autoreleased object. I have access to the source for this library, so I can do this, but I was wondering if there was a solution I could employ from the calling side if I wasn't able to modify the library.
It's too bad that the logical bridge modifier isn't working for you.
Two possible approaches leap out at me.
First, while it's not elegant, you could just write your own image release function, for example:
// ImageManualMemoryManagement.h
#import <UIKit/UIKit.h>
int releaseImage(UIImage *img);
and
// ImageManualMemoryManagement.m
#import "ImageManualMemoryManagement.h"
int releaseImage(UIImage *img)
{
[img release];
return 0;
}
In your project's target settings, under Build Phases, double click on this one .m source file under "Compile Sources" and add the non-ARC flag, -fno-objc-arc (to allow you to use the release method).
You now have a function you can call that will reduce the retain count of your UIImage and then all is good in the world again.
Second, the more dramatic solution would be to write your own non-ARC wrapper class around the entire C interface that your image library presents, remedying those few methods that aren't returning items with the correct retain count. But it seems like a lot of work for just one retainCount transgression. But if the library has it's own weaknesses (e.g. you're dealing with a clumsy low-level library), you might kill two birds with one stone.
According to apple's Transitioning to ARC Release Notes, __unsafe_unretained should be used here.
__unsafe_unretained specifies a reference that does not keep the referenced object alive and is not set to nil when there are no strong references to the object. If the object it references is deallocated, the pointer is left dangling.
Because ARC and MRC (manual reference counting) has different memory management rules, no keyword that has memory management influence works. The only choice is the keyword __unsafe_unretained which has no memory management influence to both ARC and MRC.

Objective C - difference between init and constructor?

I'm trying to find the difference between init and constructor in Objective C.I'm not a C developer, but I need to convert some Objective C-code to Java and actually I can't understand the difference between both things.
In Objective-C, the way an object comes to life is split into two parts: allocation and initialization.
You first allocate memory for your object, which gets filled with zeros (except for some Objective-C internal stuff about which you don't need to care):
myUninitializedObjectPointer = [MyClass alloc];
The next stage is initialization. This is done through a method that starts with init by convention. You should stick to this convention for various reasons (especially when using ARC), but from a language point of view there's no need to.
myObjectPointer = [myUnitializedObjectPointer init];
or in one line:
myObjectPointer = [[MyClass alloc] init];
In other languages these init methods are called constructors, but in Objective-C it is not enforced that the "constructor" is called when the object is allocated. It's your duty to call the appropriate init method. In languages like C++, C# and Java the allocation and initialization are so tightly coupled that you cannot allocate an object without also initializing it.
So in short: the init methods can be considered to be constructors, but only by naming convention and not language enforcement. To Objective-C, they're just normal methods.

Memory management semantics of Objective C "new"

Is "new" an equivalent of "alloc init" or "alloc init autorelease"?
I cannot seem to find it in any tutorial or article that deals with Cocoa memory management.
Thanks for advise.
How about this one. Read them, understand them, they're simple.
new returns an object with a retain count of 1, just like [[alloc] init]. The object is not autoreleased.
+[NSObject new] is functionally equivalent to +[NSObject alloc] followed by -[NSObject init] (i.e. [[alloc] init]).
To answer your question, from the NSObject class docs:
If you are using managed memory (not
garbage collection), this method
retains the object before returning
it. The returned object is not
autoreleased. The invoker of this
method is responsible for releasing
the returned object, using either
release or autorelease.
Using new is rare in modern Cocoa code. Most Cocoa developers favor explicit, clear code over saving a couple of key strokes. Thus alloc/init is preferred.

Why are alloc and init called separately in Objective-C?

Note: I'm relatively new to Objective-C and am coming from Java and PHP.
Could someone explain to me why I always have to first allocate and then initialize an instance?
Couldn't this be done in the init methods like this:
+ (MyClass*)init {
MyClass *instance = [MyClass alloc];
[instance setFoo:#"bla"];
return instance;
}
+ (MyClass*)initWithString:(NSString*)text {
MyClass *instance = [MyClass init];
[instance setFoo:text];
return instance;
}
...
Is this just a relict from the old C days or is there something that I'm not seeing?
I know this isn't a problem as I could as well always call alloc and init, but since it's a bit tedious I'd like to at least know why I'm doing it.
I'm liking the expressiveness of the language so far, but this is something that I want to fully understand in order to think the Objective-C way.
Thank you!
+new ends up sending an +alloc message to the class and an -init message to whatever comes back from +alloc.
The reason that NeXT departed from Stepstone's convention of using the +new message (which was a Smalltalk idea) is that early on, they encountered situations where they wanted to be able to initialize the same object more than once.
Because creating an instance and initializing an instance are two separate jobs.
You send an alloc message to the class to get an uninitialized instance. You must then initialize the instance, and you often have several ways to do that. For example:
myStr = [[NSString alloc] init]; //Empty string
myStr = [[NSString alloc] initWithFormat:#"%#.%#", parentKeyPath, key];
myStr = [[NSString alloc] initWithData:utf16data encoding:NSUnicodeStringEncoding error:&error];
myStr = [[NSString alloc] initWithContentsOfURL:URL encoding:NSUTF8StringEncoding error:&error];
Each of these initializes the string in a completely different way. How you initialize the string depends on what you want to initialize it from.
Of course, nobody likes writing alloc and then init and then autorelease every time, so you usually have convenience methods (e.g., stringWithFormat:) that do all three steps for you.
Edit: For more on this topic, including essential insights from commenters, see my blog post “Reunification”.
See NSZone.
+alloc is a shortcut cut for +allocWithZone:, which is a mechanism Cocoa provides for optimizing memory allocation.
So you have the option to do something like this:
foo = [[NSString allocWithZone:MyZone] initWithString:#"Foo"];
foo2 = [foo copyWithZone:MyZone];
The idea behind memory zones is that if you have a large number of similar objects that are frequently allocated and deallocated it may more efficient to use a separate memory zone for those objects.
In order for zoning to be effective you'd want to have +allocWithZone: available to every NSObject subclass, hence you need to separate allocation and initialization. You can create and use all the shortcuts you want, like +new, but underneath it all you need an -init method that initializes an object that has already been allocated.
"Separating the allocation and initialization stages of instance creation provides many benefits. It’s possible to use any variation of the +alloc class method to allocate an instance and then use any available initializer with the new instance.This makes it possible to create your own initialization methods without needing to provide alternate implementations of all allocation methods.
New allocation methods are seldom created because the existing methods meet almost every need. However, one or more new initializers are created for almost every class. Due to the separation of allocation and initialization stages, initializer implementations only have to deal with the variables of new instances and can completely ignore the issues sur- rounding allocation.The separation simplifies the process of writing initializers. Furthermore, Cocoa standard initializers like -initWithCoder: work with instances regardless of the way memory for the instance was allocated.
One negative consequence of the separation of allocation and initialization is the need to be aware of conventions such as the designated initializer.You must know which methods are designated initializers and how to create and document new initializers in sub- classes. In the long run, using designated initializers simplifies software development, but there is an argument to be made that theTwo-Stage Creation pattern adds to the early learning curve for Cocoa developers."
(c) Cocoa Design Patterns by Erik M. Buck and Donald A. Yacktman
You don't have to. You can use [MyClass new]. This is similar to your hypothetical init method.
Basically, Objective-C, which didn't have garbage collection initially, separates the concept of memory allocation and class initialization. That's why there are two distinct methods. When you call alloc, you are explicitly allocating memory.
Most classes have what you are asking for. You have gotten answers before on why this is like it is and why you wouldn't always want to use this all the time but if you read the documentation to classes you will see many class methods that act this way and they are often used.
For NSString you have, for example:
+ (id)string // (Empty string)
+ (id)stringWithFormat:... // Formatted string (like you use)
+ (id)stringWithContentsOfURL:... // String populated with contents of URL
And so on. And you would then use this like: NSString *myString = [NSString stringWithFormat:#"Hello %#\n", userName];
Most other classes have this, like NSArray:
+ (id)array
+ (id)arrayWithContentsOfFile:...
+ (id)arrayWithContentsOfURL:...
+ (id)arrayWithObjects:...
You just need to read the documentation. :) And read the other replies on why you don't want to use this too much.
alloc : Memory is allocated/given to the object-reference. Now reference has the possession of the memory but has not done anything yet. This memory be empty(rarest case) or with some anonymous data.
alloc and init : Allocated memory is cleaned/emptied. Memory is initiated by zero bit.
alloc and initwithdata... : Allocated memory is initiated with desired data respected to properties of the class.
For example when you purchase a plot you get the possession. This plot is given to you as it is, ruined bricks or old house may be there. This is alloc.
When you clean your plot and remove all dirt and litter. This is alloc with init.
When you build that into some valuable house it becomes more meaningful to you. And it is alloc initwith...