值類型與引用類型,可變與不可變

類型本質(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 的范圍取出來(lái),按照int的方式轉(zhuǎn)出來(lái),當(dāng)做值,&a 可以取到 a 的地址。

引用類型:變量對(duì)應(yīng)的內(nèi)存地址的內(nèi)容當(dāng)做內(nèi)存地址,再去取改地址的內(nèi)容。
例如 int *b; b 的內(nèi)容是個(gè)地址,通過(guò) *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 的,可變和不可變通過(guò)繼承來(lái)實(shí)現(xiàn)。
基類指針可以指向子類,那么 NSString *s1 可以指向 NSMutableString,那 NSString 不可變的意義就沒(méi)了。

實(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)來(lái)
}
// 傳出時(shí)
- (NSArray *)personArray {
     NSMutableArray *array = [[NSMutableArray alloc] init];
     [array addObject:p1];
     [array addObject:p2];
     ...
    return [array copy];    // 按照類型傳出
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 多線程、特別是NSOperation 和 GCD 的內(nèi)部原理。運(yùn)行時(shí)機(jī)制的原理和運(yùn)用場(chǎng)景。SDWebImage的原...
    LZM輪回閱讀 2,108評(píng)論 0 12
  • iOS面試小貼士 ———————————————回答好下面的足夠了------------------------...
    不言不愛(ài)閱讀 2,241評(píng)論 0 7
  • 史上最全的iOS面試題及答案 iOS面試小貼士———————————————回答好下面的足夠了----------...
    Style_偉閱讀 2,557評(píng)論 0 35
  • 早晨,陽(yáng)光中下著暴雨 注定開(kāi)始了我痛苦的一天 拿著一本的成績(jī) 被一所不好的大學(xué)(學(xué)院調(diào)擋) 我無(wú)奈 放棄,我的心里...
    寒嘯同學(xué)在努力閱讀 331評(píng)論 0 1
  • 智能手機(jī)的普及,讓越來(lái)越多的人成為低頭族,不管是上班的還是上學(xué)的,凡是有手機(jī)的,百分之九十九都在低頭玩手機(jī)。手機(jī)...
    滿分達(dá)人閱讀 1,364評(píng)論 0 3

友情鏈接更多精彩內(nèi)容