Почему переменные ведут себя так странно? - PullRequest
2 голосов
/ 29 апреля 2009

Я думал, что переменная в target-c - это просто ссылка на объект где-то в памяти. Таким образом, для моего понимания, результат должен быть «один», потому что в конце я назначаю адрес памяти объекта str1 для str2, а ранее я должен был назначить адрес памяти str2 для проверки.

NSString *str1 = [NSString stringWithCString:"one"];
NSString *str2 = [NSString stringWithCString:"two"];

test = str2; // test is an instance variable. I use no getter/setter here! just for testing!
str2 = str1;
NSLog(test); // = "two" ??

Ответы [ 3 ]

7 голосов
/ 29 апреля 2009

Вот как работают указатели. Результат, который вы видите, является нормальным и правильным.

Давайте перечислим все ваши переменные и на какие строки они указывают в памяти при объявлении:

str1 -> "One"
str2 -> "Two"

Затем вы выполняете некоторые инструкции присваивания:

test = str2;

Это присваивает значение указателя str2 test. Таким образом, указатели

str1 -> "One"
str2 -> "Two"
test -> "Two"

Тогда

str2 = str1;

Назначает значение указателя str1 str2. Теперь указатели

str1 -> "One"
str2 -> "One"
test -> "Two"

Затем вы печатаете test, который указывает на то, на что str2 изначально указывал, что означает «Два».

Я думаю, вы считаете, что, поскольку вы присвоили str2 значению str1 и test значению str2, значение str1 каким-то образом переходит в test. Это не вариант. Как только значение test назначено, информация о том, откуда это значение пришло, теряется. Если вы хотите, чтобы значение test было таким же, как str1, вы можете изменить порядок операций присваивания:

str2 = str1;
test = str2;
0 голосов
/ 29 апреля 2009

Переменная является контейнером. Назначение берет все, что находится справа, и помещает его в то, что слева. Другими словами, он копирует значение из одной переменной в другую; в этом случае эти значения являются указателями (адресами памяти).

Итак, вот что вы сделали:

  1. Возьмите адрес из переменной str2 и поместите тот же адрес в переменную test.
  2. Возьмите адрес из переменной str1 и поместите тот же адрес в переменную str2.

Шаг 2 не влияет на переменную test; Ваше единственное присвоение этой переменной было на шаге 1.

Внимание! Вы не копируете адрес ; вы копируете сам адрес . По-прежнему есть только одна строка «два», но между шагами 1 и 2 адрес этого объекта находится в str2 и test. Затем, на шаге 2, вы заменяете адрес в str2 на адрес строки «one», которая также существует в str1, оставляя test в качестве единственной переменной, которая все еще содержит адрес «two» строка.

Кстати, stringWithCString: устарело. Вместо этого используйте stringWithUTF8String: или stringWithCString:encoding:.

0 голосов
/ 29 апреля 2009

У вас есть это:

test = str2; // test is an instance variable.testing!
str2 = str1;
NSLog(test); // = "two" ??

Теперь давайте представим, что все эти переменные были целыми числами.

В первой строке переменной test задано значение переменной str2. Во второй строке переменной str2 присваивается значение переменной str1. В третьей строке мы выводим значение test, и это действительно значение, которое str2 было, когда мы назначали str2 для проверки. Это действительно не имеет значения, что мы впоследствии присвоили str2 другое значение.

Хорошо, но переменные - это, по сути, указатели, а не целые числа.

Неважно: думать о указателе как о просто числе, адресе где-то в памяти. И передача этого в NSLog заставляет NSLog печатать не значение указателя, а значение того, на что указывает указатель, который является массивом char.

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