问题
If I have a C-string like this:
const char* str= "hello";
I know well that I can't change any character of the string because the pointer is const.
But if I have this:
- (CLLocationDistance)distanceFromLocation:(const CLLocation *)location
I can still mutate the object state using it's methods.
If the pointer is to a NSMutableString, I'm still able to mutate it.
Then what does the const stand for?
回答1:
In that method declaration, location
is a pointer to a constant CLLocation
. But when you send a message to the location
object, the const
-ness is not preserved; the method that handles the message sees self
as a non-const
object. (Note that this is different than C++, which supports const
member functions where this
is a pointer to a constant object.)
So the const
in that declaration is not particularly useful. Perhaps it was written by someone used to the C++ way of doing things.
When you do see const
attached to an object pointer in Objective-C, it is usually like this:
extern NSString * const SomeConstantString;
This declares SomeConstantString
as a constant pointer to some non-constant object (in this case, an NSString
). The pointer itself is constant, so your program can't change SomeConstantString
to point to some other NSString
object.
回答2:
I know well that I can't change any character of the string because the pointer is const.
No, the pointer is mutable. The characters it points to are const.
I can still mutate the object state using it's methods.
There is no const-correctness for Objective-C objects like there is in C++. The compiler does not care which messages (mutating or not) you send to a const object. So there's no sense in declaring a pointer to a const object. The cited framework method is an anomaly, probably an oversight.
回答3:
Mind the difference:
// constant pointer
char * const str = "";
// pointer to constant (two equivalent ways)
const char * str = "";
char const * str = "";
The keyword const applies applies to whatever is immediately to its left. If there is nothing to its left, it applies to whatever is immediately to its right.
In Objective-C all method parameters are always passed by value. This includes primitives, structs, unions, and pointers, and any other made up type.
Note that you can't have variables of type object. A expression like NSObject o;
produces a compiler error with message "Interface type cannot be statically allocated".
The only way to pass an object is passing a pointer. The pointer is passed as value, but lets the code inside the method reference the object and change it. So in a way, it is as if you are passing the object by reference (in reality you are passing the pointer by value).
When compiling an Objective-C program, the methods are turned into C functions, and each "message send" (aka "method call", though it isn't exactly the same) is ran using the runtime function objc_sendMsg
. This function doesn't know or care if you qualified the object with const
or not. If you want an immutable object, you have to code that immutability inside the object. Example:
// const qualifying an object is ignored whether in variables or method arguments:
const NSMutableArray *array = [NSMutableArray new]; // const is ignored
-(void)someMethod:(const NSMutableArray *)array { ... // const is ignored
// calling the methods that mutate the object works fine
[array removeAllObjects];
来源:https://stackoverflow.com/questions/13652508/what-does-the-const-specifier-do-before-a-pointer-to-object