Following the usual short-circuit evaluation question, does short-circuit evaluation work for parameters built and sent against nil objects? Example:
NSMutableArray *nil_array = nil;
....
[nil_array addObject:[NSString stringWithFormat:@"Something big %@",
function_that_takes_a_lot_of_time_to_compute()]];
Is that slow function going to be called or will the whole addObject call be optimized out without processing the parameters?
A message is always dispatched to an object pointer, regardless of whether it points to an object or points to nil
. Additionally, messages are sent in the runtime and therefore the compiler cannot just assume nil_array
really is nil
and optimize it away. What if the initialization did something else, and nil_array
turns out to be an instance?
That means all the expressions you pass as arguments to your methods will be evaluated in order to be passed, so no short-circuiting of any sort happens. Your slow function will be executed, and if it takes a long time it'll affect the performance of your program.
EDIT: I just whipped up a little test case for the heck of it (empty Objective-C command line program). If you run this and observe the debugger console, you'll notice that output from all three calls to function_that_takes_a_lot_of_time_to_compute()
appears (in 5-second intervals), while output from only t1
's and t3
's test:
methods appears — naturally, since these are not nil
.
main.m
#import "Test.h"
int function_that_takes_a_lot_of_time_to_compute(void)
{
static int i = 1;
sleep(5);
NSLog(@"%d", i);
return i++;
}
int main(int argc, const char *argv[])
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
Test *t1 = [[Test alloc] init], *t2 = nil, *t3 = [[Test alloc] init];
[t1 test:function_that_takes_a_lot_of_time_to_compute()];
[t2 test:function_that_takes_a_lot_of_time_to_compute()]; // nil
[t3 test:function_that_takes_a_lot_of_time_to_compute()];
[t1 release];
[t3 release];
[pool drain];
return 0;
}
Test.h
@interface Test : NSObject {}
- (void)test:(int)arg;
@end
Test.m
@implementation Test
- (void)test:(int)arg
{
NSLog(@"Testing arg: %d", arg);
}
@end
Output
1 Testing arg: 1 2 3 Testing arg: 3