Objective-C Programming – Usage of Const

constobjective c

Related: “sending 'const NSString *' to parameter of type 'NSString *' discards qualifiers” warning

Sometimes, I think it's useful though. I may need to pass an a table and want to make sure that the content of the table does not change.

However, in most Objective-C program samples, I never see const. My question is why?

Best Answer

Due to the way that Objective-C objects work, const gives up being an enforcement and starts being a notation for the programmer. Consider this program:

int f(const int x) {
    return ++x;
}

int main(int argc, char *argv[]) {
    @autoreleasepool {
        int x = 3;
        NSLog(@"%d", f(x));
    }
    return 0;
}

That actually won't compile here (I'm using clang): the compiler can detect the attempt to modify the primitive C type and emits an error. But now compare it with this program:

NSMutableString *f2(const NSMutableString * const x) {
    [x appendString: @" world!"];
    return x;
}

int main(int argc, char *argv[]) {
    @autoreleasepool {
        NSMutableString *x = [@"Hello" mutableCopy];
        NSLog(@"%@", f2(x));
    }
    return 0;
}

Even though the function is passed a constant pointer to a constant object, it's still possible to mutate the object.

In object-oriented programming, the best way to enforce the constant nature of an object is to make that object immutable - i.e. don't provide any methods that can change its state. Imagine that the function above took an NSString argument instead of NSMutableString, and that I'd passed the literal @"Hello" instead of a mutable copy. There is now, reasonably speaking, no chance of mutating the passed-in object[*]. Objective-C doesn't have any way of enforcing that though, unlike const or final object references in other OO languages.

For comparison, const works entirely differently in C++. If I get a const reference to a C++ object, I'm only allowed to call const member functions on that object. These functions preserve the const-ness of the object, either by not making any changes or by only modifying member variables that have explicitly been marked mutable by the class designer. So imagine that I had some type MutableString in C++ that's equivalent to NSMutableString in Objective-C. The equivalent of my example above would look something like:

MutableString& f3(const MutableString& x) {
  x.appendString(" world!");
  return x;
}

This definitely won't compile: in addition to appendString() not being a const operation, the function removes the const qualifier from the type reference which requires a const_cast.

[*]I expect there is some contorted way of doing it, but now we're into the realms of one programmer trying to sabotage another by doing "clever" things.