self和this的不同

在Java和C++中,this总是指的是当前实例地址,而在静态方法也就是类方法中,是不可以使用this的。在Objectvie-C中,self是既可以出现在实例方法中,也可以出现在类方法中,并且在不同的方法中有不同的意义。在实例方法中self代表实例地址,而在类方法中,self代表该Class对象地址。

#import <Foundation/Foundation.h>

@interface X : NSObject

- (void)printSelf;
+ (void)printSelf;

@end

@implementation X

- (void)printSelf {
    NSLog(@"-printSelf:%@", self);
}

+ (void)printSelf {
    NSLog(@"+printSelf:%@", self);
}

@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        X *x = [[X alloc] init];
        [X printSelf];
        [x printSelf];
    }
    return 0;
}

上面的代码分别使用实例方法和类方法打印self,下面是控制台的输出:

可以看到实例方法确实打印出了实例地址,而类方法只打印了一个类名X,但是通过汇编代码并观察寄存器rdi(rdi中包含的就是传递给NSLog的self值)的值,我们可以看到

SelfTest`+[X printSelf]:
    0x100000e30 <+0>:  pushq  %rbp
    0x100000e31 <+1>:  movq   %rsp, %rbp
    0x100000e34 <+4>:  subq   $0x10, %rsp
    0x100000e38 <+8>:  leaq   0x219(%rip), %rax         ; @"+printSelf:%@"
    0x100000e3f <+15>: movq   %rdi, -0x8(%rbp)
    0x100000e43 <+19>: movq   %rsi, -0x10(%rbp)
    0x100000e47 <+23>: movq   -0x8(%rbp), %rsi
->  0x100000e4b <+27>: movq   %rax, %rdi
    0x100000e4e <+30>: movb   $0x0, %al
    0x100000e50 <+32>: callq  0x100000ef6               ; symbol stub for: NSLog
    0x100000e55 <+37>: addq   $0x10, %rsp
    0x100000e59 <+41>: popq   %rbp
    0x100000e5a <+42>: retq 

rdi中的值为:

这和实例方法打印的值不同。

实际上,对于main函数中调用的类方法:

[X printSelf]

完全可以替换为下面的形式:

[[X class] printSelf]

[X class]返回的就是类X的class实例,而+printSelf方法中的self指代的就是这个class对象的地址。

时间: 2024-09-29 16:40:59