我正在做这个简单的Objective-C练习以更好地理解ARC,它是一个程序,当引用设置为Strong时应该显示R2D2,当一个设置为Weak时应该失败。但是,即使有警告说该对象将被释放,代码仍会编译。
的main.m
#import <Foundation/Foundation.h>
#import "Robot.h"
int main(int argc, const char * argv[])
{
@autoreleasepool {
Robot *robot = [[Robot alloc]init];
robot.firstString =[[NSString alloc]initWithFormat:@"R%d",2];
robot.secondString = [[NSString alloc]initWithFormat:@"D%d",2];
NSLog(@"%@%@",robot.firstString,robot.secondString);
}
return 0;
}
Robot.m
#import "Robot.h"
@implementation Robot
@end
Robot.h
#import <Foundation/Foundation.h>
@interface Robot : NSObject
@property (strong) NSString *firstString;
@property (weak) NSString *secondString;
@end
谢谢
答案 0 :(得分:3)
哦,这很有趣。你正在遇到一个标记的指针。
@interface Robot : NSObject
@property (strong) NSString *firstString;
@property (weak) NSString *secondString;
@end
@implementation Robot
@end
int main(int argc, const char * argv[])
{
@autoreleasepool {
Robot *robot = [[Robot alloc]init];
robot.firstString =[[NSString alloc]initWithFormat:@"R%d",2];
robot.secondString = [[NSString alloc]initWithFormat:@"D%d",2];
NSLog(@"%@ %@",robot.firstString,robot.secondString);
NSLog(@"%p %p",robot.firstString,robot.secondString);
robot.secondString = [[NSString alloc]initWithFormat:@"argy bargy foo foo %d",2];
NSLog(@"%@ %@",robot.firstString,robot.secondString);
NSLog(@"%p %p",robot.firstString,robot.secondString);
}
return 0;
}
输出:
R2 D2
0x325225 0x324425
R2 (null)
0x325225 0x0
请注意,您的弱字符串有奇数地址。但分配不能落在奇数地址上!事实上,堆上的分配通常对齐16个字节(尽管静态分配的特殊情况字符串可能只是偶数地址)。
奇怪的地址意味着1
中有bit 0
。这表示正在使用标记指针。也就是说,字符串在对象的地址中编码,运行时检测到低位被设置,因此特殊情况下它被标记为指针。
实际上,如果您在ASCII表中查找0x32
和0x44
,前者是字符2
,后者是字符D
。 0x25
是字符串(2)和类索引(+低位)的长度。
所以,你永远不会看到弱引用变为零,因为没有涉及分配。如果没有分配,就永远不会有释放,因此,字符串引用永远不会无效。
第二个字符串 - @"argy bargy foo foo 2
- 不适合标记指针,因此是一个堆分配。
答案 1 :(得分:-3)
编译器很聪明。编译器可以替换
[[NSString alloc]initWithFormat:@"D%d",2]
与
@"D2"
这是一个NSString常量,永远不会被释放。另一种可能性:优化编译器替换
Robot *robot = [[Robot alloc]init];
robot.firstString =[[NSString alloc]initWithFormat:@"R%d",2];
robot.secondString = [[NSString alloc]initWithFormat:@"D%d",2];
NSLog(@"%@%@",robot.firstString,robot.secondString);
与
Robot *robot = [[Robot alloc]init];
NSString* tmp1 =[[NSString alloc]initWithFormat:@"R%d",2];
NSString* tmp2 = [[NSString alloc]initWithFormat:@"D%d",2];
robot.firstString = tmp1;
robot.secondString = tmp2;
NSLog(@"%@%@",tmp1,tmp2);
然后用
NSString* tmp1 =[[NSString alloc]initWithFormat:@"R%d",2];
NSString* tmp2 = [[NSString alloc]initWithFormat:@"D%d",2];
NSLog(@"%@%@",tmp1,tmp2);
然后用
NSString* tmp1 =@"R2";
NSString* tmp2 = @"D2";
NSLog(@"%@%@",tmp1,tmp2);
然后用
NSLog(@"R2D2");