What does the const specifier do, before a pointer

2019-02-26 19:55发布

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?

3条回答
Luminary・发光体
2楼-- · 2019-02-26 20:23

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楼-- · 2019-02-26 20:28

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];
查看更多
放我归山
4楼-- · 2019-02-26 20:45

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.

查看更多
登录 后发表回答