Указатели всегда равны нулю при объявлении? - PullRequest
13 голосов
/ 31 января 2012

Я обнаружил, что разные люди / статьи (например, этот ответ SO ) предполагают, что значение указателей в Objective-C не определено, пока вы не назначите ему что-то.Однако на практике я обнаружил, что они автоматически устанавливаются на nil даже до того, как я вызову alloc - для меня выполняется следующий код без подтверждения:

NSString* foo;          // 1
assert(foo==nil);       // foo is nil
foo = [NSString alloc]; // 2
assert(foo!=nil);       // after alloc, not nil.
foo = [foo init];       // 3
assert(foo!=nil);       // still not nil

Можно / нужно ли на это полагаться??Это гарантировано или я просто запускаю мой компилятор (XCode) в каком-то режиме отладки?(Я новичок в Objective-C).

Следственный вопрос: какова правильная терминология для описания foo в состоянии в конце строк, отмеченных 1, 2 и 3?Я полагаю, что по крайней мере один из 1 и 2 из них называется «неинициализированным», а один из 2 и 3 «инициализирован», но какой и как мы называем третий вариант?

Ответы [ 4 ]

29 голосов
/ 31 января 2012

Под ARC , все указатели объекта устанавливаются на nil при инициализации.Если не использовать ARC или использовать указатели на другие типы данных, неинициализированный указатель будет иметь значение мусора (и фактически чтение из указателя приводит к неопределенному поведению в соответствии со стандартом C).


@Чак указывает на что-то важное: это относится только к локальным переменным.Любая переменная со статическим хранением (статические функции или глобальные переменные) и переменные экземпляра всегда инициализируются равными их нулевому значению (которое для указателей равно nil / NULL).

6 голосов
/ 31 января 2012

(Для ARC, см. Ответ Кевина)

Могу ли я на это положиться?

Нет - никогда не полагаться на это.Стековая память обычно обнуляется в сборках отладки (зависит от настроек вашего компилятора).При включенной оптимизации компилятор не сделает этого за вас, и вам будут даны значения мусора, основанные на том, что в последний раз существовало в области стека.

Вы можете полагаться на обнуление ivars в инициализаторах ваших объектов.

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

Следственный вопрос: какова правильная терминология для описания foo в состоянии в конце строк, отмеченных 1, 2 и 3?Я полагаю, что по крайней мере один из 1 и 2 из них называется «неинициализированным», а один из 2 и 3 «инициализирован», но какой и как мы называем третий вариант?

  1. Неинициализированный
  2. Экземпляр objc, который был выделен, но не был инициализирован (иначе использовать небезопасно)
  3. Инициализированный экземпляр или объект objc.
1 голос
/ 31 января 2012

Ответ на ваш следующий вопрос:

После # 1 foo был объявлен , но неинициализирован .

После # 2 foo был выделен , но все еще неинициализирован .

После # 3, foo инициализирован .

На практике вы никогда не хотите разделять шаги 2 и 3, то есть ваш код должен быть foo = [[NSString alloc] init]. Причина этого в том, что «опасно» выделять объект, а не инициализировать его или неправильно инициализировать.

Если вы просто сделаете это foo = [NSString alloc], но забудете когда-либо вызывать init, использовать foo небезопасно, поскольку он не был инициализирован. Точно так же небезопасно делать это [foo init] (обратите внимание на отсутствие переназначения для foo), потому что init может возвращать ссылку на инициализированный объект, отличную от той, которая была первоначально выделена alloc.

0 голосов
/ 10 февраля 2016

В ARC Environment объекты автоматически устанавливаются на ноль. Но всегда полезно назначать значение объектам во время инициализации.

Я только что выполнил тест с obj-c в среде ARC

NSString *testStr ;
if (testStr == nil) {
    NSLog(@"Test Successful");
}

OutPut : Тест пройден успешно

NSString *testStr = nil;
if (testStr == nil) {
    NSLog(@"Test Successful");
}

OutPut : Тест пройден успешно

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...