ALTN
ALTN

Reputation: 699

Objective C pointers to primitive types

I came from a java background and I'm trying to figure out if translating the following piece of java code:

public class SomeClass {
    private int[] someArray;
    //+....other instance variables

    public SomeClass(int arraySize) {
        this.someArray = new int[arraySize];
        //some other initialization
    }
}

could be safely translated to Objective C as follows:

@implementation SomeClass
{
    int *_myArray;
    //some other private fields...
}

-(instancetype)initWithArraySize:(int)arraySize
{
    if(self = [super init]) {
        int newArray[arraySize];
        _myArray = newArray;
        //some other initializations
    }
    return self;
}
}

I'm obviously aware of NSArray and NSNumber boxing but the above code sounds cleaner and more efficient, specially that my app will need at some cases to hold thousands of references to SomeClass. At the same time I'm not sure if primitive pointers are safe to use with ARC and whether they could cause leaks.

I've tried the following dummy test to see if things would work as expected:

@implementation SomeClassTests
{
    int *_myArray;
    //some other private fields...
}

- (void)testExample {
    int array[] = {4, 2, 1, 0};
    _myArray = array;

    [self changeArray:_myArray];
    XCTAssertEqual(_myArray[0], -1);
    XCTAssertEqual(_myArray[1], -1);
    XCTAssertEqual(_myArray[2], 1);
}

-(void)changeArray:(int *)array
{
    array[1] = -1;
    array[0] = -1;
}
}

The test passed, but I'm still not feeling really confident.

Any thoughts guidance would be highly appreciated.

Upvotes: 1

Views: 376

Answers (2)

trojanfoe
trojanfoe

Reputation: 122401

Your implementation will lead to serious errors as you allocate newArray on the stack and pass a pointer to the instance variable someArray, however once that method returns the stack will be recovered, making the someArray a dangling pointer.

It's more normal in Objective-C to use an NSArray of NSNumber objects for this. If you want to create an array that can be added to after initialization, and otherwise modified, then use an NSMutableArray:

@implementation SomeClass
{
    NSMutableArray *_someArray;
}

-(instancetype)initWithArraySize:(int)arraySize
{
    if(self = [super init]) {
        _someArray = [[NSMutableArray alloc] initWithCapacity:arraySize];
    }
    return self;
}

Upvotes: 1

Vlad Papko
Vlad Papko

Reputation: 13302

In Java code sample you allocate memory in Heap, but in Objective C code sample you allocate memory in Stack.

Here is variant with allocation in Heap:

-(instancetype)initWithArraySize:(int)arraySize
{
    if(self = [super init]) {
        _myArray = malloc(arraySize * sizeof(int));
        //some other initializations
    }
    return self;
}

- (void)dealloc {
    if (_myArray != NULL) {
        free(_myArray);
    }
}

Upvotes: 1

Related Questions