情况1:请问如果对象A指向并持有对象B,如果A超出其变量生命周期,那么对象B的引用计数是否会减一。
情况2:对象A自己生成后并没有autoreless,A超出其生命周期,那么A生成的对象是否还依然占用内存。
自学ios低段选手请各位大神指教,并且想大家推荐一下这方面的书籍,因为项目用的是非arc而且也觉得这是一门手艺,需要钻研。
|
|
情况1:b 引用计数-1
情况2:永远不会。
|
|
理论上是这样的,我也懂但是测试结果让我迷茫。。
测试代码:
NSObject *a = [[NSObject alloc] init];
NSLog(@”a retinaCount: %d”,a.retainCount);
if (1==1) {
NSObject *b =[a retain];
NSLog(@”a retinaCount: %d”,a.retainCount);
NSLog(@”b retinaCount: %d”,b.retainCount);
}
NSLog(@”a retinaCount: %d”,a.retainCount);
打印结果
2015-04-07 17:13:32.782 [491:71729] a retinaCount: 1
2015-04-07 17:13:32.782 [491:71729] a retinaCount: 2
2015-04-07 17:13:32.783 [491:71729] b retinaCount: 2
2015-04-07 17:13:32.783 [491:71729] a retinaCount: 2
请大神教诲
|
|
额 刚才的例子好像有问题 我有更改了一下例子 但是打印结果不变
测试例子:
NSObject *a = [[NSObject alloc] init];
NSLog(@”a retinaCount: %d”,a.retainCount);
if (1==1) {
NSObject *b =a;
[b retain];
NSLog(@”a retinaCount: %d”,a.retainCount);
NSLog(@”b retinaCount: %d”,b.retainCount);
}
NSLog(@”a retinaCount: %d”,a.retainCount);
|
|
你是手动管理内存的,这个例子会造成内存泄漏,如果是支持ARC的编译器,编译时会在你的 NSLog(@”b retinaCount: %d”,b.retainCount)之后插入[b release]。
我在这个帖子中有过类似的回答:
http://bbs.csdn.net/topics/390936473
|
|
主要还是要遵循手动 内存管理的几个口诀:
1. 谁创建,谁释放(类似于“谁污染,谁治理”)。如果你通过alloc、new或copy来创建一个 对象,那么你必须调用release或autorelease。换句话说,不是你创建的,就不用你去释放。
2. 除了alloc、new或copy之外的方法创建的对象都被声明了autorelease。
3. 谁retain,谁release。只要你调用了retain,无论这个对象是如何生成的,你都要调用release。
|
|
情况1:b 引用计数-1
情况2:永远不会。
理论上是这样的,我也懂但是测试结果让我迷茫。。
测试代码:
NSObject *a = [[NSObject alloc] init];
NSLog(@”a retinaCount: %d”,a.retainCount);
if (1==1) {
NSObject *b =[a retain];
NSLog(@”a retinaCount: %d”,a.retainCount);
NSLog(@”b retinaCount: %d”,b.retainCount);
}
NSLog(@”a retinaCount: %d”,a.retainCount);
打印结果
2015-04-07 17:13:32.782 [491:71729] a retinaCount: 1
2015-04-07 17:13:32.782 [491:71729] a retinaCount: 2
2015-04-07 17:13:32.783 [491:71729] b retinaCount: 2
2015-04-07 17:13:32.783 [491:71729] a retinaCount: 2
请大神教诲
这是没有问题的,当使用:
NSObject *a = [[NSObject alloc] init];
来创建一个对象的时候会产生两个东西,一个是存储在栈区的指向对象的指针变量a ,还有一个就是指针变量a指向的对象,并且这个对象的retainCount 为1
接下来这句:
NSObject *b =[a retain];
新建一个指针变量b它也指向了指针a指向的堆中的对象,使用retain后,这个对象的retainCount变成了2,这时a,b指向的是同一个对象。
在使用:
NSLog(@"a retinaCount: %d",a.retainCount);
NSLog(@"b retinaCount: %d",b.retainCount);
输出时,由于a,b 指向的是同一块内存,且内存中的对象的retainCount为2,所以控制台输出为 2
|
|
主要还是要遵循手动内存管理的几个口诀:
1. 谁创建,谁释放(类似于“谁污染,谁治理”)。如果你通过alloc、new或copy来创建一个对象,那么你必须调用release或autorelease。换句话说,不是你创建的,就不用你去释放。
2. 除了alloc、new或copy之外的方法创建的对象都被声明了autorelease。
3. 谁retain,谁release。只要你调用了retain,无论这个对象是如何生成的,你都要调用release。
感谢大神指教,其实这些我也都懂。在书上网上实践都用上了。
但是在实践和代码中遇到的一些问题还是有些不明白,或者说网上看到的和试验结果并不一致
主要还是变量周期和引用计数之间的关系
验证代码:
NSObject *a = [[NSObject alloc] init];
NSLog(@”a retinaCount: %d”,a.retainCount);
if (1==1) {
NSObject *b =a; // b的变量生命周期只在这个if函数内,但是持有变量a所指向的内存地址。
[b retain];
NSLog(@”a retinaCount: %d”,a.retainCount);
NSLog(@”b retinaCount: %d”,b.retainCount);
}
NSLog(@”a retinaCount: %d”,a.retainCount); // 已经超出了变量b的生命周期,但是a所指向的内存地址的引用计数还是2
输出结果:
2015-04-08 11:04:52.016[942:193538] a retinaCount: 1
2015-04-08 11:04:52.016[942:193538] a retinaCount: 2
2015-04-08 11:04:52.017[942:193538] b retinaCount: 2
2015-04-08 11:04:52.017[942:193538] a retinaCount: 2
|
|
主要还是要遵循手动内存管理的几个口诀:
1. 谁创建,谁释放(类似于“谁污染,谁治理”)。如果你通过alloc、new或copy来创建一个对象,那么你必须调用release或autorelease。换句话说,不是你创建的,就不用你去释放。
2. 除了alloc、new或copy之外的方法创建的对象都被声明了autorelease。
3. 谁retain,谁release。只要你调用了retain,无论这个对象是如何生成的,你都要调用release。
感谢大神指教,其实这些我也都懂。在书上网上实践都用上了。
但是在实践和代码中遇到的一些问题还是有些不明白,或者说网上看到的和试验结果并不一致
主要还是变量周期和引用计数之间的关系
验证代码:
NSObject *a = [[NSObject alloc] init];
NSLog(@”a retinaCount: %d”,a.retainCount);
if (1==1) {
NSObject *b =a; // b的变量生命周期只在这个if函数内,但是持有变量a所指向的内存地址。
[b retain];
NSLog(@”a retinaCount: %d”,a.retainCount);
NSLog(@”b retinaCount: %d”,b.retainCount);
}
NSLog(@”a retinaCount: %d”,a.retainCount); // 已经超出了变量b的生命周期,但是a所指向的内存地址的引用计数还是2
输出结果:
2015-04-08 11:04:52.016[942:193538] a retinaCount: 1
2015-04-08 11:04:52.016[942:193538] a retinaCount: 2
2015-04-08 11:04:52.017[942:193538] b retinaCount: 2
2015-04-08 11:04:52.017[942:193538] a retinaCount: 2
你没有调用[b release],当然还是2,b只是指向了a的地址,然后retain了a的对象,b的作用域结束后,你访问不到b了,但是
b指向的对象还是有的
|
|
主要还是要遵循手动内存管理的几个口诀:
1. 谁创建,谁释放(类似于“谁污染,谁治理”)。如果你通过alloc、new或copy来创建一个对象,那么你必须调用release或autorelease。换句话说,不是你创建的,就不用你去释放。
2. 除了alloc、new或copy之外的方法创建的对象都被声明了autorelease。
3. 谁retain,谁release。只要你调用了retain,无论这个对象是如何生成的,你都要调用release。
感谢大神指教,其实这些我也都懂。在书上网上实践都用上了。
但是在实践和代码中遇到的一些问题还是有些不明白,或者说网上看到的和试验结果并不一致
主要还是变量周期和引用计数之间的关系
验证代码:
NSObject *a = [[NSObject alloc] init];
NSLog(@”a retinaCount: %d”,a.retainCount);
if (1==1) {
NSObject *b =a; // b的变量生命周期只在这个if函数内,但是持有变量a所指向的内存地址。
[b retain];
NSLog(@”a retinaCount: %d”,a.retainCount);
NSLog(@”b retinaCount: %d”,b.retainCount);
}
NSLog(@”a retinaCount: %d”,a.retainCount); // 已经超出了变量b的生命周期,但是a所指向的内存地址的引用计数还是2
输出结果:
2015-04-08 11:04:52.016[942:193538] a retinaCount: 1
2015-04-08 11:04:52.016[942:193538] a retinaCount: 2
2015-04-08 11:04:52.017[942:193538] b retinaCount: 2
2015-04-08 11:04:52.017[942:193538] a retinaCount: 2
你没有调用[b release],当然还是2,b只是指向了a的地址,然后retain了a的对象,b的作用域结束后,你访问不到b了,但是
b指向的对象还是有的
我的理解是b对象虽然没有了 但是a所指向的内存地址的持有依然没有被-1 。 也就是说b对a指向内存地址的持有并没有消除。 还有那本书我手上也有,但是也没有着重解释这个问题。。
|
|
为了验证问题2,采用以下例子:
NSObject *a = nil;
if (1==1) {
NSObject *b=[[NSObject alloc] init]; // b的变量生命周期只在这个if函数内。
a=b;
NSLog(@”a retinaCount: %d”,a.retainCount);
NSLog(@”b retinaCount: %d”,b.retainCount);
}
NSLog(@”a retinaCount: %d”,a.retainCount); // 已经超出了变量b的生命周期,但是a所指向的内存地址的引用计数还是1
输出:
2015-04-08 13:14:17.056[1004:214379] a retinaCount: 1
2015-04-08 13:14:17.057[1004:214379] b retinaCount: 1
2015-04-08 13:14:17.058[1004:214379] a retinaCount: 1
证明虽然b已经过了生命周期 但是其所创建的内存空间依然没有释放并且 retinaCount依然为1. 与问题1相互印证。这个地方没有一个准确的说法。反正实验结果是这样的。。。
|
20分 |
主要还是要遵循手动内存管理的几个口诀:
1. 谁创建,谁释放(类似于“谁污染,谁治理”)。如果你通过alloc、new或copy来创建一个对象,那么你必须调用release或autorelease。换句话说,不是你创建的,就不用你去释放。
2. 除了alloc、new或copy之外的方法创建的对象都被声明了autorelease。
3. 谁retain,谁release。只要你调用了retain,无论这个对象是如何生成的,你都要调用release。
感谢大神指教,其实这些我也都懂。在书上网上实践都用上了。
但是在实践和代码中遇到的一些问题还是有些不明白,或者说网上看到的和试验结果并不一致
主要还是变量周期和引用计数之间的关系
验证代码:
NSObject *a = [[NSObject alloc] init];
NSLog(@”a retinaCount: %d”,a.retainCount);
if (1==1) {
NSObject *b =a; // b的变量生命周期只在这个if函数内,但是持有变量a所指向的内存地址。
[b retain];
NSLog(@”a retinaCount: %d”,a.retainCount);
NSLog(@”b retinaCount: %d”,b.retainCount);
}
NSLog(@”a retinaCount: %d”,a.retainCount); // 已经超出了变量b的生命周期,但是a所指向的内存地址的引用计数还是2
输出结果:
2015-04-08 11:04:52.016[942:193538] a retinaCount: 1
2015-04-08 11:04:52.016[942:193538] a retinaCount: 2
2015-04-08 11:04:52.017[942:193538] b retinaCount: 2
2015-04-08 11:04:52.017[942:193538] a retinaCount: 2
你没有调用[b release],当然还是2,b只是指向了a的地址,然后retain了a的对象,b的作用域结束后,你访问不到b了,但是
b指向的对象还是有的
我的理解是b对象虽然没有了 但是a所指向的内存地址的持有依然没有被-1 。 也就是说b对a指向内存地址的持有并没有消除。 还有那本书我手上也有,但是也没有着重解释这个问题。。
在{ }中定义的变量b ,在{} 的范围内是b 的作用域,虽然在{} 外无法访问到b,但这不叫超出了b的生命周期。b 依然指向那个对象,那个对象的引用计数仍然为2, 只有当b 收到release消息时,对象的引用计数才会相应的减1. 如果没有release操作,对象不会释放,内存泄露。
|
|
为了验证问题2,采用以下例子:
NSObject *a = nil;
if (1==1) {
NSObject *b=[[NSObject alloc] init]; // b的变量生命周期只在这个if函数内。
a=b;
NSLog(@”a retinaCount: %d”,a.retainCount);
NSLog(@”b retinaCount: %d”,b.retainCount);
}
NSLog(@”a retinaCount: %d”,a.retainCount); // 已经超出了变量b的生命周期,但是a所指向的内存地址的引用计数还是1
输出:
2015-04-08 13:14:17.056[1004:214379] a retinaCount: 1
2015-04-08 13:14:17.057[1004:214379] b retinaCount: 1
2015-04-08 13:14:17.058[1004:214379] a retinaCount: 1
证明虽然b已经过了生命周期 但是其所创建的内存空间依然没有释放并且 retinaCount依然为1. 与问题1相互印证。这个地方没有一个准确的说法。反正实验结果是这样的。。。
你是看的什么书?书上怎么说的?你这个例子是正常的,你分配的内存没有释放,肯定是1啊,对象是分配在堆上的,NSObject *b是栈中的一个指针,指向堆中的内存地址,b的作用域结束后,你就访问不到b的指针了
|
|
主要还是要遵循手动内存管理的几个口诀:
1. 谁创建,谁释放(类似于“谁污染,谁治理”)。如果你通过alloc、new或copy来创建一个对象,那么你必须调用release或autorelease。换句话说,不是你创建的,就不用你去释放。
2. 除了alloc、new或copy之外的方法创建的对象都被声明了autorelease。
3. 谁retain,谁release。只要你调用了retain,无论这个对象是如何生成的,你都要调用release。
感谢大神指教,其实这些我也都懂。在书上网上实践都用上了。
但是在实践和代码中遇到的一些问题还是有些不明白,或者说网上看到的和试验结果并不一致
主要还是变量周期和引用计数之间的关系
验证代码:
NSObject *a = [[NSObject alloc] init];
NSLog(@”a retinaCount: %d”,a.retainCount);
if (1==1) {
NSObject *b =a; // b的变量生命周期只在这个if函数内,但是持有变量a所指向的内存地址。
[b retain];
NSLog(@”a retinaCount: %d”,a.retainCount);
NSLog(@”b retinaCount: %d”,b.retainCount);
}
NSLog(@”a retinaCount: %d”,a.retainCount); // 已经超出了变量b的生命周期,但是a所指向的内存地址的引用计数还是2
输出结果:
2015-04-08 11:04:52.016[942:193538] a retinaCount: 1
2015-04-08 11:04:52.016[942:193538] a retinaCount: 2
2015-04-08 11:04:52.017[942:193538] b retinaCount: 2
2015-04-08 11:04:52.017[942:193538] a retinaCount: 2
你没有调用[b release],当然还是2,b只是指向了a的地址,然后retain了a的对象,b的作用域结束后,你访问不到b了,但是
b指向的对象还是有的
我的理解是b对象虽然没有了 但是a所指向的内存地址的持有依然没有被-1 。 也就是说b对a指向内存地址的持有并没有消除。 还有那本书我手上也有,但是也没有着重解释这个问题。。
在{ }中定义的变量b ,在{} 的范围内是b 的作用域,虽然在{} 外无法访问到b,但这不叫超出了b的生命周期。b 依然指向那个对象,那个对象的引用计数仍然为2, 只有当b 收到release消息时,对象的引用计数才会相应的减1. 如果没有release操作,对象不会释放,内存泄露。
果然版主,能理解我的疑问并且指出问题所在。我去研究一下oc指针变量生命周期的问题。感谢
|