Сравнение NSNumber с оператором <(less) вместо сравнения - PullRequest
3 голосов
/ 26 сентября 2011

несколько дней назад я читал пост, написанный другим пользователем, относительно сравнений между объектами NSNumber с использованием оператора <(less). Он получал неправильные результаты, и люди говорили ему, что вместо этого сравниваются адреса объектов NSNumber их значений ... Я пытался воспроизвести проблему, но мне чего-то не хватает: </p>

int main (int argc, char*argv[])
{
        NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
        NSMutableArray *arrayDistance = [NSMutableArray array];

        [arrayDistance addObject:
                [NSNumber numberWithInteger: 10]];
        [arrayDistance addObject:
                [NSNumber numberWithInteger: 20]];
        [arrayDistance addObject:
                [NSNumber numberWithInteger: 8]];
        [arrayDistance addObject:
                [NSNumber numberWithInteger: 9]];

        int iMinor = 0;
        int i;
        for (i = 0; i < [arrayDistance count]; i++) {
                if([arrayDistance objectAtIndex: i] < [arrayDistance objectAtIndex: iMinor])
                {
                        iMinor = i;
                }
        }

        NSLog(@"iMinor is %d", iMinor);

        [pool release];

        return 0;
}

Код выше корректно возвращает 2, почему? Разве это не должно сравнивать адреса вместо значений объектов NSNumber в массиве arrayDistance? Разве не нужно извлекать целочисленное значение из объектов NSNumber или использовать метод сравнения объектов NSNumber?

Перегружает ли класс NSNumber оператор <(less) для сравнения фактических значений, хранящихся в объектах? Если да, то где это написано в справочной документации? </p>

Надеюсь, вопрос ясен. Заранее благодарю за любую помощь.

1 Ответ

11 голосов
/ 26 сентября 2011

Код выше правильно возвращает 2, почему? Разве это не должно сравнивать адреса вместо значений объектов NSNumber в массиве arrayDistance? Разве не нужно извлекать целочисленное значение из объектов NSNumber или использовать метод сравнения объектов NSNumber?

Он сравнивает адреса NSNumber objects, и да, вы должны либо получить базовое целочисленное значение, либо использовать -compare:.

То, что происходит под капотом, заключается в том, что Lion использует теговые указатели для (подмножество) NSNumber экземпляров, представляющих целые числа. Из-за тегового представления указателя адреса в вашем конкретном примере имеют тот же порядок, что и целые числа, которые они представляют.

Если вы печатаете фактические адреса с помощью

printf("%p\n", [arrayDistance objectAtIndex:i]);

вы получите:

0xac3
0x14c3
0x8c3
0x9c3

Игнорирование младшего значащего байта:

0xa  = 10
0x14 = 20
0x8  = 8
0x9  = 9

Как видите, эти адреса отображают целочисленные значения.

Обратите внимание, что это детали реализации, которые варьируются в зависимости от целевой платформы и могут измениться в будущем. Вы не должны зависеть от этого.

Перегружает ли класс NSNumber оператор <(less) для сравнения фактических значений, хранящихся в объектах? Если да, то где это написано в справочной документации? </p>

Нет, в Objective-C нет перегрузки операторов.

...