Это допустимое использование указателя Objective C? - PullRequest
6 голосов
/ 21 марта 2009

Это вопрос начального уровня, в котором мне любопытно, допустимо ли использование указателя в выражении, таком как:

 NSMutableDictionary *foo = [bar mutableCopy];

Я запутался, когда это действительно так, когда мне нужно было сделать следующее:

NSMutableDictionary *foo = [[NSMutableDictionary alloc] initWithCapacity:0];
foo = [bar mutableCopy];
// use foo
[foo release];

Действительны ли оба? Когда использовать один поверх другого?

Ответы [ 5 ]

9 голосов
/ 23 марта 2009

Догадываясь, почему вы можете быть смущены, я хотел бы добавить объяснение того, что на самом деле делает второй пример кода (и почему это не нужно).

NSMutableDictionary *foo = [[NSMutableDictionary alloc] initWithCapacity:0];

Я думаю, что вы запутались в этой строке, потому что эта строка часто описывается как "инициализация foo". Это немного вводит в заблуждение. С технической точки зрения, здесь изменяются 2 разных объекта - создается новый объект NSMutableDictionary, а переменной "foo" назначается его адрес.

Строка фактически создает новый объект NSMutableDictionary в куче (область динамической памяти вашего приложения). Я назову это «Словарь 1». Чтобы найти этот новый объект «Словарь 1» в куче, его адрес памяти сохраняется в «foo». Роль "foo" заключается в том, чтобы выступать в качестве индекса, поэтому мы можем найти "Словарь 1".

Хотя мы часто говорим: «foo - это словарь», это потому, что мы ленивы - это утверждение технически неверно. Правильно: «в куче есть словарь, и foo хранит адрес своей памяти, чтобы мы могли его найти и использовать».

Когда вы запускаете строку:

foo = [bar mutableCopy];

вы используете адрес в "баре", чтобы найти другой объект (я назову его "Словарь 2") в куче, и сделать еще один объект ("Словарь 3") в куче с теми же значениями , Если вы ведете счет, то теперь существует 3 объекта.

После того как "Словарь 3" создан, его адрес в памяти затем сохраняется в переменной "foo". Это сохранение в «foo» перезаписывает существующий адрес памяти (тот, который указывал на «Словарь 1»). Это означает, что у нас нет оставшихся указателей на «Словарь 1» и, следовательно, мы никогда не сможем найти его снова. Вот почему мы говорим, что «Словарь 1» просочился.

Я надеюсь, что из этой ситуации вы можете понять, почему «Словарь 1» никогда не был нужен (вы когда-либо намеревались использовать «foo» для доступа к копии, «Словарь 3»).

7 голосов
/ 21 марта 2009

Вам никогда не понадобится писать код во втором примере. [[NSMutableDictionary alloc] initWithCapacity:0] ничего не делает, кроме утечки памяти.

Во втором примере вы создаете NSMutableDictionary и назначаете его на foo. Затем в следующей строке вы назначаете копию другого NSMutableDictionary на foo, что означает, что исходный словарь foo, на который указывает указатель, теперь просто уплывает где-то в куче и не может быть освобожден.

Вам потребуется разблокировать foo в любом случае, как изложено в Рекомендации по управлению памятью Objective-C .

3 голосов
/ 21 марта 2009

Первый правильный, второй утечка памяти, потому что вы выделяете дважды (копия считается за один) и освобождает только один раз.

Не забудьте выпустить foo после того, как вы закончите

1 голос
/ 21 марта 2009

Акт присваивания заменяет предыдущее значение, хранящееся в этой переменной. Например:

x = 3
x = 4

Значение, хранящееся в начале второй строки в x, равно 3, но после выполнения строки кода - 4. Синтаксис:

int x = 0;

- это просто сокращение для этого:

int x;
x = 0;

Переменные, которые являются указателями, ничем не отличаются. Таким образом, если первая ссылка переменной просто присвоить ей, вам не нужно сначала ее инициализировать, потому что любое значение, с которым вы ее инициализируете, просто отбрасывается.

0 голосов
/ 21 марта 2009

Первый - правильный способ сделать это. И copy, и alloc будут выделять память для вашей переменной. Таким образом, использование второго параметра увеличит количество сохраняемых переменных до 2.

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