статические переменные в Objective-C — что они делают?

Я видел несколько сообщений, в которых обсуждалось, что такое статическая переменная, и я думаю, что понял, но я хотел бы быстро написать (или найти) программу, которая использует как обычную, так и статическую переменную, рядом, и посмотреть как/когда они работают по-разному. Немного быстрого и грязного кода, может быть, две переменные int и пара операторов отслеживания NSLog, просто чтобы увидеть, ЧЕМ они отличаются.

У кого-нибудь есть какие-нибудь советы/идеи/код, которые иллюстрируют, чем статический var отличается от обычного?


person Sirab33    schedule 11.02.2011    source источник


Ответы (3)


Как в C, так и в Objective-C переменная static — это переменная, которая выделяется на все время жизни программы. В отличие от автоматических переменных, время жизни которых существует во время одного вызова функции; и динамически размещаемые переменные, такие как объекты, которые могут быть освобождены из памяти, когда они больше не используются. Проще говоря, значение статической переменной сохраняется на протяжении всех вызовов функций/методов. При объявлении вне функции статическая переменная видна всем в пределах файла, в котором она объявлена; при объявлении внутри функции или метода оно видно только внутри этой функции или метода, но значение сохраняется между вызовами.

Скажите, что у вас есть это:

int f(void)
{
    int i = 5;
    i += 10;
    return i;
}

Каждый вызов f() будет возвращать значение 15.

Теперь скажите, что у вас есть это:

int g(void)
{
    static int i = 5;
    i += 10;
    return i;
}

При первом вызове g() будет возвращено значение 15. Во второй раз будет возвращено 25, поскольку i сохранило свое значение 15, а затем увеличилось на 10. Будет возвращен третий вызов, 35. И так далее.

В контексте классов Objective-C статические переменные часто используются для имитации переменных класса, поскольку в Objective-C нет переменных класса (в других языках, таких как Java, они есть). Например, предположим, что вы хотите лениво инициализировать объект и вернуть только этот объект. Вы можете увидеть это:

static MyObject *obj = nil;

@implementation MyObject

+ (id)sharedObject
{
    if (obj == nil) obj = [[MyObject alloc] init];
    return obj;
}

@end

obj будет инициализирован при первом вызове classObject; последующие вызовы classObject вернут тот же объект. Вы можете проверить это, записав адрес объекта:

NSLog(@"obj is at %p", [MyObject sharedObject]);
NSLog(@"obj is at %p", [MyObject sharedObject]);    // Will print the same address both times

Кроме того, obj будет виден всем методам в MyObject.

Этот метод также используется для реализации одноэлементных классов в Objective-C.

person mipadi    schedule 11.02.2011
comment
Очень хорошее объяснение - хотя кажется, что соглашение об именах наоборот! :-) Я имею в виду следующее: слово STATIC означает что-то, что НЕ изменяется, и все же его статическая переменная - судя по вашему примеру int f (void) vs. int g (void) - это та, значение которой кажется постоянно меняться - это совсем не статично! - person Sirab33; 11.02.2011
comment
если подумать, почему тогда он называется статическим? что статичного в этом? - person Sirab33; 11.02.2011
comment
Безусловно, лучший пост, который я нашел о статической переменной ObjC на SO. Но с одной оговоркой: sharedObject обычно является методом класса и возвращает экземпляр класса. - person Philip007; 10.12.2012
comment
@Philip007: Упс, да, это опечатка. Спасибо за наводку! - person mipadi; 10.12.2012
comment
Не проблема. Просто помните, что вы также можете изменить часть NSLog. Кроме того, в одноэлементном шаблоне я бы поместил static MyObject *obj = nil; внутри sharedObject. Потому что это, вероятно, единственное место, где вы можете получить доступ к obj. - person Philip007; 10.12.2012
comment
Исходя из Java, этот синтаксис имеет static int i = 5; внутри метода всегда сбивает меня с толку. Я всегда думаю о присваивании внутри метода как о присвоении i нового значения 5. - person Khon Lieu; 11.03.2013
comment
Еще одно примечание: если переменная определена как статическая в файле заголовка, то каждый файл реализации (.m), который включает файл заголовка, получает собственную копию этой переменной. - person RPM; 10.07.2013
comment
В g() что именно происходит в этой первой строке (static int i = 5;) при втором (и последующих) вызовах? Компилятор просто игнорирует присваивания, содержащиеся в последующих объявлениях статической переменной? - person Tim Arnold; 15.04.2014
comment
@TimArnold: По сути, он выделяется один раз, как и переменная static верхнего уровня, за исключением того, что i имеет область действия g(). - person mipadi; 15.04.2014
comment
@TimArnold Если вы поставите там точку останова, вы увидите, что она никогда не вернется к этой строке, чтобы сбросить ее на всю жизнь программы. - person smileBot; 01.11.2014
comment
Даже если я удалю статическое слово, оно зарегистрирует те же адреса памяти, и в этом случае объект obj будет доступен для всего класса MyObject. Тогда в чем тут разница? - person Confused; 27.05.2016

static работает в основном как в C.

  1. Он может либо инициализировать переменную только один раз.

  2. Объявление статической переменной в файле выше @implementationblock будет доступно только для всего файла.

person chunkyguy    schedule 11.02.2011

«статический» относится больше к атрибутам переменной (кто, что, где), а не только к значению. В отличие от других языков, где это относится исключительно к значению.

  • Прикреплено

Это похоже на привязку переменной к определенному месту, будь то внутри функции или в реализации.

  • Личное

Он имеет атрибуты, аналогичные «частным» var, в том смысле, что он невидим для братьев и сестер или родителей, но дети могут получить к нему доступ.

  • Стильный

Это объявление со значением по умолчанию. Как и в других языках, где вы определяете переменные внутри класса и присваиваете им значение «по умолчанию»:

private int myNumber = 3;

Это дает нам «классоподобные» переменные внутри функций. Объявите их один раз, затем, когда функция манипулирует значением, значение сохраняется. При следующем вызове функции значение будет таким же, как и после предыдущего «цикла», точно так же, как вы ожидаете, что значение переменной класса останется после манипуляции.

person bob    schedule 11.12.2013