類型本質(zhì)
變量:一個(gè)內(nèi)存地址的別名
例如 int a = 0;
a : 0x0004拄轻,int 32位婚度,那么 a 的范圍是 [0x0004, 0x0006)
a
0x4 0x5 0x6
00000000 00000000 00000000 00000000 00000000
值類型:變量對(duì)應(yīng)的內(nèi)存地址的內(nèi)容當(dāng)做數(shù)值。
例如 int a = 0; a 的范圍取出來进宝,按照int的方式轉(zhuǎn)出來刻坊,當(dāng)做值,&a 可以取到 a 的地址党晋。
引用類型:變量對(duì)應(yīng)的內(nèi)存地址的內(nèi)容當(dāng)做內(nèi)存地址谭胚,再去取改地址的內(nèi)容徐块。
例如 int *b; b 的內(nèi)容是個(gè)地址,通過 *b 取得該地址內(nèi)容灾而。
如果定義了三級(jí)指針 int ***b; 那么需要 &&&b 取得內(nèi)容胡控。
- 需要注意的點(diǎn)
int a = 10;
int *b = &a;
int *c = &a;
b, c 兩個(gè)指針指向同一個(gè)地址的數(shù)據(jù),那么很可能 b 的數(shù)據(jù)被 c 改掉旁趟。
如果你允許多個(gè)指針改同一份數(shù)據(jù)昼激,那可以這樣用。例如
void fun() {
Person *me = new Person();
editName(me);
editAge(me);
editSex(me);
// me 里就收集到了全部數(shù)據(jù)
}
如果不希望多個(gè)指針改同一份數(shù)據(jù)锡搜,造成數(shù)據(jù)錯(cuò)誤橙困,那么應(yīng)該copy一份。例如
int a = 10;
int *b = malloc(sizeof(int));
*b = a;
int *c = malloc(sizeof(int));
*c = a;
// 那么修改 b 不會(huì)影響到 c
如果是 Person 這樣的類耕餐,例如
Class Person {
int a;
int *b;
Hand *h; // h 里面還有指針變量
};
Person p, p1, p2;
p1 = p.copy;
p2 = p.copy;
在淺拷貝的時(shí)候凡傅,只復(fù)制 Person,a 會(huì)被復(fù)制肠缔,p1.a 和 p2.a 修改不影響夏跷,但是 p1.b 和 p2.b 還是指向同一塊數(shù)據(jù),還是有可能被錯(cuò)誤修改明未。
需要深拷貝槽华,對(duì) p 中的指針也進(jìn)行拷貝,對(duì)指針中的指針亚隅,一直下去硼莽,直到它不是個(gè)指針為止的數(shù)據(jù)都要進(jìn)行拷貝,才是完全的兩個(gè) p1, p2煮纵。
可變與不可變
有些指針的數(shù)據(jù)是可變的懂鸵,有些指針的數(shù)據(jù)是肯定不會(huì)變化的(那么在copy的時(shí)候可以只copy指針而不copy內(nèi)容),為了區(qū)分?jǐn)?shù)據(jù)可不可變行疏,那么定義了可變與不可變的類型匆光。
C++ 中用 const 區(qū)分
int const *p = &a; // 內(nèi)容不可變
int * const p = &a; // 指針不可變
int const * const p = &a; // 指針,內(nèi)容都不可變
oc 中用 Mutable 區(qū)分酿联, swift 中 var 與 let
NSString *s1 = @"abcd"; // 內(nèi)容不可變终息,但指針可變,p 可以指其他
NSMutableString *s2 = [[NSMutableString alloc] init]; // 指針贞让,內(nèi)容都可變
oc中少了指針不可變周崭。
oc中第二個(gè)風(fēng)險(xiǎn)
@interface NSMutableString : NSString
NSMutableString 是繼承 NSString 的,可變和不可變通過繼承來實(shí)現(xiàn)喳张。
基類指針可以指向子類续镇,那么 NSString *s1 可以指向 NSMutableString,那 NSString 不可變的意義就沒了销部。
實(shí)際中 NSString 可能是可以變的摸航,當(dāng)他指向 NSMutableString 的時(shí)候制跟。
怎么避免,類型要對(duì)上
// 傳入時(shí)
NSMutableString *s2 = [[NSMutableString alloc] init];
for (int i=0; i<10; i++) {
[s2 appendString:@"xxx"];
[self dealString:[s2 copy]]; // 防止改變string
}
- (void)dealString:(NSString *)str {
NSString *a = [str copy]; // 防止別人傳 NSMutableString 進(jìn)來
}
// 傳出時(shí)
- (NSArray *)personArray {
NSMutableArray *array = [[NSMutableArray alloc] init];
[array addObject:p1];
[array addObject:p2];
...
return [array copy]; // 按照類型傳出
}