Почему переменные ведут себя так странно?
-
03-07-2019 - |
Вопрос
Я думал, что переменная в objective-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" ??
Решение
Вот как работают указатели.Результат, который вы видите, нормальный и правильный.
Давайте перечислим все ваши переменные и на какие строки они указывают в памяти по мере их объявления:
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
s, вы должны изменить порядок ваших операций присвоения в обратном порядке:
str2 = str1;
test = str2;
Другие советы
У тебя есть это:
test = str2; // test is an instance variable.testing!
str2 = str1;
NSLog(test); // = "two" ??
Теперь давайте представим, что все эти переменные были целыми числами.
В первой строке переменная test
устанавливается в значение переменной str2
.Во второй строке переменная str2
устанавливается в значение переменной str1
.В третьей строке мы выводим значение test
, и это действительно та ценность, которая str2
это было, когда мы назначили str2
чтобы проверить.На самом деле совершенно не имеет значения, что мы впоследствии назначили str2
другое значение.
Хорошо, но вы говорите, что переменные на самом деле являются указателями, а не целыми числами.
Неважно:думайте о указателе как о простом числе, адресе где-то в памяти.И передача этого в NSLog заставляет NSLog выводить не значение указателя, а значение того, на что указывает указатель, который является массивом char .
Переменная - это контейнер.Задание берет все, что находится на правой стороне, и помещает это также во все, что находится на левой стороне.Другими словами, он копирует значение из одной переменной в другую;в данном случае эти значения являются указателями (адресами памяти).
Итак, вот что вы сделали:
- Возьмите адрес, который есть в
str2
переменную и поместить тот же адрес вtest
переменная. - Возьмите адрес, который есть в
str1
переменную и поместить тот же адрес вstr2
переменная.
Шаг 2 не влияет на test
переменная;ваше единственное присвоение этой переменной было выполнено на шаге 1.
Важный:Ты не копируешь что находится на адрес;ты копируешь сам адрес.По-прежнему есть только одна строка “two”, но между шагами 1 и 2, адрес того, что объект находится в обоих str2
и test
.Затем, на шаге 2, вы заменяете адрес в str2
с адресом строки “one”, которая также существует в str1
, оставляя test
как единственная переменная, которая все еще содержит адрес строки “two”.
Кстати, stringWithCString:
устарел.Использование stringWithUTF8String:
или stringWithCString:encoding:
вместо этого.