美文网首页程序员
值类型与引用类型,可变与不可变

值类型与引用类型,可变与不可变

作者: ck2016 | 来源:发表于2017-11-23 18:44 被阅读0次

类型本质

变量:一个内存地址的别名
例如 int a = 0;
a : 0x0004,int 32位,那么 a 的范围是 [0x0004, 0x0006)

a
0x4               0x5               0x6
00000000 00000000 00000000 00000000 00000000

值类型:变量对应的内存地址的内容当做数值。
例如 int a = 0; a 的范围取出来,按照int的方式转出来,当做值,&a 可以取到 a 的地址。

引用类型:变量对应的内存地址的内容当做内存地址,再去取改地址的内容。
例如 int *b; b 的内容是个地址,通过 *b 取得该地址内容。

如果定义了三级指针 int ***b; 那么需要 &&&b 取得内容。

  • 需要注意的点

int a = 10;
int *b = &a;
int *c = &a;
b, c 两个指针指向同一个地址的数据,那么很可能 b 的数据被 c 改掉。

如果你允许多个指针改同一份数据,那可以这样用。例如

void fun() {
    Person *me = new Person();
    editName(me);
    editAge(me);
    editSex(me);
    // me 里就收集到了全部数据
}

如果不希望多个指针改同一份数据,造成数据错误,那么应该copy一份。例如

int a = 10;
int *b = malloc(sizeof(int));
*b = a;
int *c = malloc(sizeof(int));
*c = a;
// 那么修改 b 不会影响到 c

如果是 Person 这样的类,例如

Class Person {
    int a;
    int *b;
    Hand *h;    // h 里面还有指针变量
};

Person p, p1, p2;
p1 = p.copy;
p2 = p.copy;
在浅拷贝的时候,只复制 Person,a 会被复制,p1.a 和 p2.a 修改不影响,但是 p1.b 和 p2.b 还是指向同一块数据,还是有可能被错误修改。

需要深拷贝,对 p 中的指针也进行拷贝,对指针中的指针,一直下去,直到它不是个指针为止的数据都要进行拷贝,才是完全的两个 p1, p2。

可变与不可变

有些指针的数据是可变的,有些指针的数据是肯定不会变化的(那么在copy的时候可以只copy指针而不copy内容),为了区分数据可不可变,那么定义了可变与不可变的类型。

C++ 中用 const 区分

int const *p = &a;    // 内容不可变
int * const p = &a;   // 指针不可变
int const * const p = &a;    // 指针,内容都不可变

oc 中用 Mutable 区分, swift 中 var 与 let

NSString *s1 = @"abcd";   // 内容不可变,但指针可变,p 可以指其他
NSMutableString *s2 = [[NSMutableString alloc] init];   // 指针,内容都可变

oc中少了指针不可变。

oc中第二个风险
@interface NSMutableString : NSString
NSMutableString 是继承 NSString 的,可变和不可变通过继承来实现。
基类指针可以指向子类,那么 NSString *s1 可以指向 NSMutableString,那 NSString 不可变的意义就没了。

实际中 NSString 可能是可以变的,当他指向 NSMutableString 的时候。

怎么避免,类型要对上

// 传入时
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 进来
}
// 传出时
- (NSArray *)personArray {
     NSMutableArray *array = [[NSMutableArray alloc] init];
     [array addObject:p1];
     [array addObject:p2];
     ...
    return [array copy];    // 按照类型传出
}

相关文章

网友评论

    本文标题:值类型与引用类型,可变与不可变

    本文链接:https://www.haomeiwen.com/subject/pjctuxtx.html