一 、對象內(nèi)存的影響因素理解
1.)場景1首先我們創(chuàng)建一個LGPerson繼承NSObject對象,里面沒有任何屬性,成員變量 和方法;
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface LGPerson : NSObject
@end
NS_ASSUME_NONNULL_END
#import "LGPerson.h"
@implementation LGPerson
@end
int main(int argc, char * argv[]) {
NSString * appDelegateClassName;
@autoreleasepool {
LGPerson *person = [LGPerson alloc];
lg_double2HEX(190.5);
lg_float2HEX(190.5);
appDelegateClassName = NSStringFromClass([AppDelegate class]);
}
return UIApplicationMain(argc, argv, nil, appDelegateClassName);
}
(lldb) po class_getInstanceSize(LGPerson.class)
8
(lldb) po class_getInstanceSize(NSObject.class)
8
(lldb)
場景1打印結(jié)果顯示:沒有添加任何成員屬性 LGPerson 與 NSObject的內(nèi)存長度都為8,兩者一樣;
2.)場景2,接著往LGPerson里面添加一個屬性name,
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface LGPerson : NSObject
//{
// NSString *name;
//}
@property (nonatomic, copy) NSString *name;
//+ (void)sayNB;
//- (void)sayNB2;
@end
NS_ASSUME_NONNULL_END
#import "LGPerson.h"
@implementation LGPerson
//+ (void)sayNB{
//}
//- (void)sayNB2;
//}
@end
int main(int argc, char * argv[]) {
NSString * appDelegateClassName;
@autoreleasepool {
LGPerson *person = [LGPerson alloc];
lg_double2HEX(190.5);
lg_float2HEX(190.5);
appDelegateClassName = NSStringFromClass([AppDelegate class]);
}
return UIApplicationMain(argc, argv, nil, appDelegateClassName);
}
(lldb) po class_getInstanceSize(LGPerson.class)
16
(lldb) po class_getInstanceSize(NSObject.class)
8
(lldb)
運(yùn)行結(jié)果發(fā)現(xiàn),此時LGPerson添加一個屬性name后,內(nèi)存長度為16,而NSObject 還是8;且在場景2基礎(chǔ)添加實例方法和類方法打印的結(jié)果一樣;在LGPerson將 name新建換成成員變量,打印結(jié)果也一樣;
3.)場景3:在場景2的基礎(chǔ)上,LGPerson多增加一個屬性
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface LGPerson : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *nickName;
@end
NS_ASSUME_NONNULL_END
(lldb) po class_getInstanceSize(LGPerson.class)
24
(lldb) po class_getInstanceSize(NSObject.class)
8
(lldb)
打印輸出結(jié)果LGPerson,內(nèi)存長度變?yōu)樵瓉?4,而NSObject 內(nèi)存長度還是8;綜合場景1,2,3,繼承NSObject的對象,可否認(rèn)為每增加一個屬性,內(nèi)存長度就加8?繼續(xù)往下做驗證:
A:
@interface LGPerson : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *nickName;
@property (nonatomic, copy) NSString *hobby;
@end
(lldb) po class_getInstanceSize(LGPerson.class)
32
(lldb)
@interface LGPerson : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *nickName;
@property (nonatomic, copy) NSString *hobby;
@property (nonatomic, assign) int age;
@end
(lldb) po class_getInstanceSize(LGPerson.class)
40
(lldb)
@interface LGPerson : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *nickName;
@property (nonatomic, copy) NSString *hobby;
@property (nonatomic, assign) int age;
@property (nonatomic) double height;
@end
(lldb) po class_getInstanceSize(LGPerson.class)
48
(lldb)
@interface LGPerson : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *nickName;
@property (nonatomic, copy) NSString *hobby;
@property (nonatomic, assign) int age;
@property (nonatomic) double height;
@property (nonatomic) char c1;
@property (nonatomic) char c2;
@end
(lldb) po class_getInstanceSize(LGPerson.class)
48
(lldb)
此時發(fā)現(xiàn),LGPerson ,每增加一個屬性,內(nèi)存長度并不就加8,而是以8字節(jié)長度方式進(jìn)行對齊的:接下來:
int main(int argc, char * argv[]) {
NSString * appDelegateClassName;
@autoreleasepool {
LGPerson *person = [LGPerson alloc];
person.name = @"Cooci";
person.nickName = @"KC";
person.age = 18;
person.height = 190.5;
person.c1 = 'a';
person.c2 = 'b';
lg_double2HEX(18);
lg_float2HEX(190.5);
appDelegateClassName = NSStringFromClass([AppDelegate class]);
}
return UIApplicationMain(argc, argv, nil, appDelegateClassName);
}
進(jìn)行打?。?/p>
(lldb) x/8gx person
0x60000366ed90: 0x00000001010b3860 0x0000001200006261
0x60000366eda0: 0x00000001010ae038 0x00000001010ae058
0x60000366edb0: 0x0000000000000000 0x4067d00000000000
0x60000366edc0: 0x0000000000000000 0x0000000000000000
(lldb) po 0x00000001010ae038
Cooci
(lldb) po 0x00000001010ae058
KC
(lldb) po 0x00000012
18
(lldb) po 0x61
97
(lldb) po 0x62
98
(lldb) e -f f -- 0x4067d00000000000
(long) $7 = 190.5
(lldb)
總結(jié):LGPerson內(nèi)存的大小受成員變量,屬性的影響,不受方法的影響,而且以某種長度方式進(jìn)行對齊的。
二、結(jié)構(gòu)體內(nèi)存對齊原則
1.對齊原則
1):數(shù)據(jù)成員對?規(guī)則:結(jié)構(gòu)(struct)(或聯(lián)合(union))的數(shù)據(jù)成員,第?個數(shù)據(jù)成員放在offset為0的地?,以后每個數(shù)據(jù)成員存儲的起始位置要從該成員??或者成員的?成員??(只要該成員有?成員,?如說是數(shù)組,結(jié)構(gòu)體等)的整數(shù)倍開始(?如int為4字節(jié),則要從4的整數(shù)倍地址開始存儲。 min(當(dāng)前開始的位置m n) m = 9 n = 4
9 10 11 12
2):結(jié)構(gòu)體作為成員:如果?個結(jié)構(gòu)?有某些結(jié)構(gòu)體成員,則結(jié)構(gòu)體成員要從其內(nèi)部最?元素??的整數(shù)倍地址開始存儲.(struct a?存有struct b,b?有char,int ,double等元素,那b應(yīng)該從8的整數(shù)倍開始存儲.)
3):收尾?作:結(jié)構(gòu)體的總??,也就是sizeof的結(jié)果,.必須是其內(nèi)部最?成員的整數(shù)倍.不?的要補(bǔ)?。
各個成員所占字節(jié)數(shù)對應(yīng)表:

2.例子1
struct LGStruct1 {
double a; // 8 [0 7]
char b; // 1 [8]
int c; // 4 (9 10 11 [12 13 14 15]
short d; // 2 [16 17] 24
}struct1;
struct LGStruct2 {
double a; // 8 [0 7]
int b; // 4 [8 9 10 11]
char c; // 1 [12]
short d; // 2 (13 [14 15] 16
}struct2;
struct LGStruct3 {
double a; // 8 [0 7]
int b; // 4 [8 9 10 11]
char c; // 1 [12]
short d; // 2 (13 [14 15] 16
int e; // 4 [16 17 18 19] 20 21 22 23 24
struct LGStruct1 str; // 24 (20 21 22 23 [24 25 26 27 ....45 46 47] 48
}struct3;
struct LGStruct4 {
double a; // 8 [0 7]
int b; // 4 [8 9 10 11]
// char c; // 1
// short d; // 2
// int e; // 4
struct LGStruct1 str; // (12 13 14 15 [16 25 26 27 ....33,34] 35 36 37 38 39 40)
}struct4;
int main(int argc, char * argv[]) {
NSString * appDelegateClassName;
@autoreleasepool {
NSLog(@"%lu-%lu-%lu-%lu",sizeof(struct1),sizeof(struct2),sizeof(struct3),sizeof(struct4));
appDelegateClassName = NSStringFromClass([AppDelegate class]);
}
return UIApplicationMain(argc, argv, nil, appDelegateClassName);
}
(lldb)
打印結(jié)果
2021-06-09 09:13:39.137431+0800 001-內(nèi)存對齊原則[82125:2053942] 24-16-48-40
(lldb)
感謝cooci老師的課程指導(dǎo),以上是學(xué)習(xí)過程中一些記錄,不足之處還請大家指出,好做改進(jìn)。