I know there are a lot of questions on pointers out there, particularly now for Objective-C. But I'm looking for some higher level answers to help me understand the paradigms in Objective-C.
I've heard some people say that using pointers in Objective-C is a matter or experience, i.e. some classes demand that you use pointers, others don't. Is this true? And is that the extent of using pointers in Objective-C.
Basically, apart from when you want to explicitly pass reference variable to methods, what are the rules for pointers in Objective-C?
You use a pointer always when referring to something on the heap and sometimes, but usually not when referring to something on the stack.
Since Objective-C objects are always allocated on the heap (with the exception of Blocks, but that is orthogonal to this discussion), you always use pointers to Objective-C objects. Both the id and Class types are really pointers.
Where you don't use pointers are for certain primitive types and simple structures. NSPoint, NSRange, int, NSUInteger, etc... are all typically accessed via the stack and typically you do not use pointers.
As for Why the * in Objective-C?, you might find this question of interest.
Related
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
what is the point of pointers in objective language
I am confused as to when and why pointers are used in Obj-C code. I am new to Obj-C and have a good grounding in C++ from an intro course at my university.
NSDate *now = [NSDate date];
Why is a pointer used here (and what exactly is its purpose?), and not here...
NSUInteger arrayLength = [<some array> count];
I am much more comfortable with the second example, but the first is still puzzles me.
It's the wording of the typedefs of Apple which are confusing.
NSUInteger
is just a fancy typedef for unsigned int; therefore it's a scalar type and not an object; you don't need a pointer to it in general for such a simple use case.
However,
NSDate
is a Foundation class; it means that its instances are proper Objective-C objects. As you probably know, Objective-C is a fully dynamic language: no static instances of classes are permitted, so every object is essentially a pointer (well, rather the allocated memory behind the pointer). So when you work with Objective-C objects, you always need a pointer to them.
Well, there are a few fundamental differences between Objective-C and C++. In Objective-C, there is actually a "generic object" (type "id"), and you can pass objects around without worrying about classes.
One of the implementation details that makes this possible is that Objective-C doesn't have "static" objects; all objects are created through the equivalent of "new" and are accessed through a pointer (string literals might be different, but they are still of type "NSString*"). It's just the way it is in Objective-C; you simply cannot have an "NSString MyString".
Because of this, the whole "objects are just objects and the compiler doesn't actually what you're dealing with" is possible because all objects are just simple pointers -- they are all the same size. The compiler can pass them around without knowing what they are, you can store them in containers without the containers knowing what they are etc.
Objective-C and C++ may both be "object-oriented" extensions of C, but they are quite different nonetheless.
EDIT: you can write stuff like "NSString* MyString" so the compiler knows what kind of object it is dealing with, but that's just convenience: you can still put other objects into that pointer (and, in fact, since the "new" equivalent usually returns id, one of the more common mistakes that I make is to "new" a different class from what the pointer says)
On the positive side, the compiler will warn you if you assign e.g. an NSWindow* to MyString, and it will also warn you if you call "open" on MyString. However, this is just an added benefit from the compiler; you could just as well declare everything as "id", or cast away the warnings.
I read this question in stackoverflow.
The excerpt answer provided by bbum is below:
The problem isn't the assignment, it is much more likely that you
declared your instance variable to be BOOL *initialBroadcast;.
There is no reason to declare the instance variable to be a pointer
(at least not unless you really do need a C array of BOOLs).. Remove
the * from the declaration.
1.Is there anything wrong in using a pointer variable even when I do not have to maintain an array of BOOLs?
2.I think even if avoiding them a good practice, it is not specific to objective-C and applies to all programming languages which has pointers.
Please answer my questions.
1.Is there anything wrong in using a pointer variable even when I do not have to maintain an array of BOOLs?
It's not illegal to do so, but it is bad practice. Using a pointer variable requires that you manage that memory (allocate and free it), and there are whole classes of bugs that can occur as a result. If you forget to allocate the memory, or accidentally modify the pointer, your program could crash, or you could overwrite some other part of memory. If you forget to free the memory, you have a memory leak. None of these things can ever happen if you're just using a plain BOOL. In addition, you get no benefit from using a pointer here; you do a bunch of extra work, and get nothing in return.
2.I think even if avoiding them a good practice, it is not specific to objective-C and applies to all programming languages which has
pointers.
I don't know about "all programming languages which [have] pointers", but I would certainly say in any C-based language (C, C++, Objective-C), it's bad practice to use pointers to intrinsic types when a plain variable of that type will do. If you can avoid doing memory management, do so.
On a side note, it is good practice to listen to everything bbum says. Seriously.
In my previous question, I figured out that all Objective-C objects are declared as pointers. But in C and C++, pointers can be accessed from any function, global or not, and they seem unprotected.
How are they "protected" in Objective-C ?
ObjC does not police your use of pointers.
There is type checking at compile time, so if you have a pointer to an NSNumber, and use the variable that holds it to assign to an NSString, the compiler will issue a warning. However, this is easily overridden by casting the pointer, as shown below,
NSNumber *myNumberPtr = [NSNumber initWithInt:99];
NSString *myStringPtr = (NSString *) myNumberPtr;
In this case, the compiler is told to keep quiet, but accessing myStringPtr as a string would cause 'undefined results', hopefully something obvious like a crash, but possibly something more pernicious.
Similarly, I could declare,
NSString *notActuallyAString = 0x897996789; // assigned some random value
Then when notActuallyAString is accessed at runtime, it is highy likely to cause a bad access exception as the pointer is almost certainly not pointing to an NSString, and quite possibly isn't a valid memory address at all.
This makes C (and its associated languages) powerful for low-level programming (if you actually know the memory mapped address of some hardware register, you can assign them in this way, and access hardware), but brings pretty clear risks.
It gets worse, because you may have a valid pointer at some point in the execution, but the memory that the pointer references is freed off at some later point. Then if you (wrongly) access that pointer, you again may well get an exception as the memory is no longer valid for the purpose the code assumes. Writing (assigning) a via a pointer that pointers somewhere it shouldn't is a common cause of memory corruption, which can be a devil to diagnose. For this reason, it's good practice (aka defensive coding) to make sure pointers that you've finished with are assigned to nil, so if you reuse those pointers when you shouldn't, you should get a symptom that is more easy to diagnose than some random memory corruption.
You need a good understanding of pointers to program in objC, and I would recommend reading the timeless classic reference book, 'The C Programming Language' by Kernighan & Ritchie which explains the basics of pointers, you can then build your understanding on how pointers and memory allocation is used in ObjC and C++.
A pointer, per se, does not have any kind of protection.
You should take a look to some basics of OOP; members can be of three types: public, protected or private. This is what decides if you can access the member from outside the implementation of the class itself (not considering, of course, some kind of hacking like accessing private members modifying directly the bytes of the object. You must not, however, do something like this because it's strongly against the OO philosophy: if a member is private there is a reason, and forcing the access to it will not give you any guarantee that your code will work with future versions of the library or in other machines).
In Objective-C members are protected by default. That's what give the protection you are looking for.
In Objective-C, instance variables are not exposed by default. In Objective-C 2.0, they are exposed by properties using the #property and #synthesize syntax. (Prior to 2.0, solely by explicitly written getter/setter methods.)
That notwithstanding, it is possible to access instance variables directly using the pointer operator syntax, e.g. NSString *bar = Foo->_text; even when text is not exposed as a property.
Further, you can now declare instance variables in your implementation file, to avoid having them exposed in public header files. If you are writing framework code, this offers some 'protection' against access to ivars outside of the property accessors since they are no longer visible.
I'm trying to interface Lua with Objective-C, and I think string conversion with NSSelectorFromString() has too big an overhead because Lua has to copy all strings to internalize them (although I'm not sure about this).
So I'm trying to find more lightweight way to represent a selector in Lua.
An Objective-C selector is an abstracted type, but it's defined as a pointer to something:
typedef struct objc_selector *SEL;
So it looks safe to handle as a regular pointer, so I can pass it to Lua with lightuserdata. Is this fine?
I don't believe it is safe to handle it as a pointer (even a void pointer), because if this ever changes in a future implementation or a different implementation of the language. I didn't see a formal Objective-C spec that tells what is implementation defines, but often when opaque types like this are used it means that you shouldn't have to know details about the underlying type is. In fact, the struct is forward-declared so that you can't access any of its members.
The other problem you might run into is implementing equality comparisons: are selectors references to a pool of constants or is each selector mutable. Once again, implementation defined.
Using C strings as suggested above is probably your best bet; ruby manages to use symbols for selectors and doesn't have too much of a performance penalty. Since the strings are const, lua doesn't need to copy them, but probably does anyway to be safe. If you can find a way to not copy the strings you might not take that much of a performance hit.
I'm getting my feet wet in Objective-C and Cocoa and I noticed that all objects are allocated out of the heap.
Is there any reason why this is the standard in Objective-C? I'm especially keen because Objective-C is considered a strict super-set of C with OO features.
I think this owes to the Smalltalk heritage.
Also, you could say that stack-allocated objects are a peculiarity of C++. Very few other languages do that, and then mostly as a low-level optimization for the compiler. In C++ it's reasonable, since one of the stated goals was to be exactly as performant as plain C.
Why do you feel this is in conflict with the fact that Objective-C is a super-set of C? After all, plain C can't either allocate objects on the stack... nor anywhere. structs, OTOH, are allowed on the stack, both on C and Objective-C
I'm not exactly answering your question, but since you are understanding Obj-C's runtime, here it goes. You can allocate objects more efficiently using NSZones. You won't have them on the stack, but at least you can avoid some fragmentation and performance issues:
link text