Pourquoi les variables se comportent-elles si étrangement?
-
03-07-2019 - |
Question
Je pensais qu'une variable dans objective-c n'était qu'une référence à un objet quelque part dans la mémoire. Donc, pour ma compréhension, le résultat doit être "un", car à la fin, j'attribue l'adresse mémoire de l'objet de str1 à str2, et j'avais auparavant assigné l'adresse mémoire de str2 à tester.
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" ??
La solution
Voici comment fonctionnent les pointeurs. Le résultat que vous voyez est normal et correct.
Énumérons toutes vos variables et les chaînes qu’elles pointent en mémoire lorsqu’elles sont déclarées:
str1 -> "One"
str2 -> "Two"
Ensuite, vous exécutez des instructions d'affectation:
test = str2;
Ceci attribue la valeur du pointeur str2
à test
. Donc, les pointeurs sont
str1 -> "One"
str2 -> "Two"
test -> "Two"
Alors
str2 = str1;
Attribue la valeur du pointeur str1
à str2
. Maintenant, les pointeurs sont
str1 -> "One"
str2 -> "One"
test -> "Two"
Ensuite, vous imprimez test
, qui pointe vers ce que str2
désignait à l'origine, à savoir "Deux".
Je pense que vous pensez que depuis que vous avez affecté str2
à la valeur de str1
, et test
à la valeur de str2
, la valeur de str1
est en quelque sorte transformée en test
. Ce n'est pas le cas. Une fois que la valeur de test
est attribuée, les informations concernant l'origine de cette valeur sont perdues. Si vous voulez que la valeur de test
soit identique à celle de str1
, vous devez inverser l'ordre de vos opérations d'affectation:
str2 = str1;
test = str2;
Autres conseils
Vous avez ceci:
test = str2; // test is an instance variable.testing!
str2 = str1;
NSLog(test); // = "two" ??
Maintenant, supposons que toutes ces variables soient des ints.
Sur la première ligne, la variable test
est définie sur la valeur de la variable str2
.
Sur la deuxième ligne, la variable str2
est définie sur la valeur de la variable str1
.
Sur la troisième ligne, nous imprimons la valeur de test
, et c’est bien la valeur que str2
était lorsque nous avons assigné str2
à tester.
Peu importe vraiment que nous ayons ensuite attribué à str2
une valeur différente.
Ok, mais les variables sont vraiment des pointeurs, dites-vous, pas des ints.
Peu importe: considérez un pointeur comme un simple nombre, l’adresse de quelque part en mémoire. Et transmettre cela à NSLog ne permet pas à NSLog d’imprimer la valeur du pointeur, mais la valeur de ce sur quoi le pointeur pointe, qui est un tableau de caractères.
Une variable est un conteneur. La mission prend tout ce qui est du côté droit et le met également dans ce qui est du côté gauche. En d'autres termes, il copie la valeur d'une variable à l'autre; dans ce cas, ces valeurs sont des pointeurs (adresses mémoire).
Alors, voici ce que vous avez fait:
- Prenez l'adresse qui se trouve dans la variable
str2
et insérez la même adresse dans la variabletest
. - Prenez l'adresse qui se trouve dans la variable
str1
et insérez la même adresse dans la variablestr2
.
L'étape 2 n'affecte pas la variable test
; votre seule affectation à cette variable était à l'étape 1.
Important: vous ne copiez pas ce qui se trouve à l'adresse; vous copiez l'adresse elle-même . Il ne reste plus qu'un & # 8220; deux & # 8221; chaîne, mais entre les étapes 1 et 2, l'adresse de cet objet est à la fois dans str2
et test
. Ensuite, à l'étape 2, vous remplacez l'adresse figurant dans str2
par l'adresse du & # 8220; one & # 8221; chaîne, qui existe également dans str1
, laissant test
comme étant la seule variable qui conserve toujours l'adresse de la & # 8220; deux & # 8221; chaîne.
BTW, stringWithCString:
est obsolète. Utilisez stringWithUTF8String:
ou stringWithCString: encoding:
à la place.