Objective c 为声明的属性合成什么等效代码?

Objective c 为声明的属性合成什么等效代码?,objective-c,gcc,memory-management,Objective C,Gcc,Memory Management,在自动合成getter和setter方法之后,它们的主体究竟是什么样子的 从官方文档中,我发现到目前为止只有推荐的实现技术,但并没有说明编译器在合成过程中使用了哪种技术: 一些技术建议实现包含autorelease消息,这对于多线程编程来说并不十分安全。我只是想知道自动生成的代码是否符合某些建议的实现 例如: .h @interface AClass: NSObject{} @property (nonatomic, retain) AnotherClass *aProp; @end

在自动合成getter和setter方法之后,它们的主体究竟是什么样子的

从官方文档中,我发现到目前为止只有推荐的实现技术,但并没有说明编译器在合成过程中使用了哪种技术:

一些技术建议实现包含
autorelease
消息,这对于多线程编程来说并不十分安全。我只是想知道自动生成的代码是否符合某些建议的实现


例如:

.h

@interface AClass: NSObject{}
    @property (nonatomic, retain) AnotherClass *aProp;
@end
.m

@implementation AClass
    @synthesize aProp

-(id) init {
    if ((self = [super init])) {
        self.aProp = [[AnotherClass alloc] init];    // setter invocation
    }
    return self;
}

-(AnotherClass *) aMethod {
    return self.aProp;     // getter invocation
}
@end
编译器生成的
aProp
的等效访问器代码段是什么

-(AnotherClass *) aProp {
    // getter body
}

-(void) setAProp: (AnotherClass *) {
    // setter body
}

它取决于您设置的属性,例如,带有RETAIN属性

- (void)setAProp:(AnotherClass *)value {
   [aProp release];
   aProp = value;
   [aProp retain];
}
对于分配属性

- (void)setAProp:(AnotherClass *)value {
   aProp = value;
}
对于复制属性(与NSString一起使用)


将属性声明为非原子时,您将得到以下结果:

// .h
@property (nonatomic, retain) id ivar;

// .m
- (id)ivar {
    return ivar;
}

- (void)setIvar:(id)newValue {
    if (ivar != newValue) {  // this check is mandatory
        [ivar release];
        ivar = [newValue retain];
    }
}
注意检查
ivar!=新值
。如果没有,ivar可以在
释放后解除锁定,并且以下
保留将导致内存访问错误

当您使用
copy
声明您的属性时,代码看起来几乎相同,将
retain
替换为
copy

对于
分配
,它更简单:

- (void)setIvar:(id)newValue {
    ivar = newValue;
}

现在,当您将属性声明为
原子时(此属性是默认属性),事情会变得稍微复杂一些。苹果的一位工程师在开发论坛上发布了一个类似于下面的片段:

- (id)ivar {
    @synchronized (self) {
        return [[self->ivar retain] autorelease];
    }
}

- (void)setIvar:(id)newValue {
    @synchronized (self) {
        if (newValue != self->ivar) {
            [self->ivar release];
            self->ivar = newValue;
            [self->ivar retain];
        }
    }
}

注意这两种方法中的
@synchronized
块和getter中的附加
retainautorelease
。这两种方法都可以确保您在读取之前的值(保留值和自动删除值)或新值时,如果该值被某个线程更改,那么您将获得该值。

是的,这取决于属性,但我们不知道苹果如何实现它,我们不应该在意。另外,您为retain提供的示例有一个bug。如果指定的值与已指定的值相同,则对象将被解除分配,因为保留计数达到0。为了避免这种情况,setProp通常会检查是否再次设置了相同的值。您可以在这里看到更多详细信息:@Kobski我们确实关心我们是否在主线程之外的线程中,因为推荐的两种技术使用了
autorelease
:如果您不指定“非原子”,那么getter和setter函数将是线程安全的。原子属性仅提供数据完整性的基本保证。每个应用程序都必须提供自己的策略来保护多个线程之间共享的数据。此外,您没有指定关于getter的任何内容,因此没有upvote。ei您如何知道编译器是否会基于此生成实现?@Martin编译器没有使用该文档中给出的任何技术。这些技术适用于实现自己的getter和setter的人。另一方面,编译器将把属性直接合成为目标代码。因此,我的答案中给出的代码只是一个高级模型,说明了如果编译器将ObjC代码生成为文本,它可能会做什么。这应该足以理解合成属性如何工作的原理。如果您想得到一个更明确的答案,您可以看看代码生成是如何在LLVM编译器中实现的。ei如何在实现了附件体(在C中,汇编程序)的情况下获得这些中间结果?对于概念级别,我已经很熟悉了,编译器版本-这就是我实际要寻找的。@Martin Lookup手册页for clang。它有一个
-S
选项来生成程序集输出?
- (id)ivar {
    @synchronized (self) {
        return [[self->ivar retain] autorelease];
    }
}

- (void)setIvar:(id)newValue {
    @synchronized (self) {
        if (newValue != self->ivar) {
            [self->ivar release];
            self->ivar = newValue;
            [self->ivar retain];
        }
    }
}