C 结构体的延迟初始化

发布于 2025-01-05 01:38:17 字数 705 浏览 0 评论 0原文

我不确定如何初始化 C 结构体或 iOS5 之前的基本类型的类属性。如果我正在处理一个类,这就是我会做的,但我不知道我可以检查什么来查看这是否是第一次访问该结构,因为它们在创建时未定义:

@interface GraphView : UIView
@property (nonatomic) CGPoint origin;
@end


@implementation GraphView
@synthesize origin = _origin;

- (CGPoint)origin
{
    if (WHAT?) {
         _origin = CGPointMake(self.bounds.origin.x + self.bounds.size.width/2, 
                               self.bounds.origin.y + self.bounds.size.height/2);
    }
    return _origin;
}

@end

我意识到延迟初始化的主要好处是内存分配,但如果我对所有属于类的属性执行此操作,那么使用相同的样式来设置所有属性的起始值似乎是最清楚的。

我可以使用其他一些实例变量或属性来跟踪 self.origin 是否已被访问,但这似乎......不顺利。在设置 self.origin 之前,我可以小心地永远不要访问它,这似乎是由于结构在创建时未定义的事实而引起的。

有“正确”的方法吗?

I'm not sure how to initialize a class property that's a C struct, or pre-iOS5 base type. This is what I'd do if I was dealing with a class, but I don't know what I can check to see if this is the first time the struct has been accessed, since they're undefined at creation:

@interface GraphView : UIView
@property (nonatomic) CGPoint origin;
@end


@implementation GraphView
@synthesize origin = _origin;

- (CGPoint)origin
{
    if (WHAT?) {
         _origin = CGPointMake(self.bounds.origin.x + self.bounds.size.width/2, 
                               self.bounds.origin.y + self.bounds.size.height/2);
    }
    return _origin;
}

@end

I realize the primary benefit of lazy initialization is for memory allocation, but if I'm doing this for all the properties that are classes, it seems clearest to use the same style for setting starting values on all my properties.

I can use some other instance variable or property to track whether the self.origin has been accessed, but that seems... not smooth. I could take care to never access self.origin before I've set it, which seems mildly entailed by the fact that structs are undefined at creation.

Is there a "right" way?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

谜泪 2025-01-12 01:38:17

objc 类的所有成员在创建时都将初始化为零(甚至是结构体)。我不明白你关于内存分配的观点。该空间是为结构保留的(您没有存储指向它的指针)。无论您是否为其赋值,它都需要相同的空间。

All members of a objc class will be initialized to zero on creation (even a struct). I do not get you point about memory allocation. The space is reserved for the struct (you are not storing a pointer to it). It will require the same space whether you have assigned it a value or not.

笑脸一如从前 2025-01-12 01:38:17

通常,您必须具有带内无效状态,例如指针的 nil 。在您的情况下,您可以测试 !CGPointEqualToPoint(_origin, CGPointZero)!CGPointEqualToPoint(_origin, CGPointMake(-1,-1)) 如果您知道这些永远不可能有效的。 (_origin 将默认为 CGPointZero,或者您必须在 init 中将其设置为 (-1, -1) if (0, 0) 是有效的。)

如果所有可能的带内值都有效,那么您就会遇到您提到的带外标志。

Generally you have to have an in-band invalid state like nil for pointers. In your case, you could test !CGPointEqualToPoint(_origin, CGPointZero) or !CGPointEqualToPoint(_origin, CGPointMake(-1,-1)) if you know those can never be valid. (_origin will default to CGPointZero or you'll have to set it to (-1, -1) in an init if (0, 0) is valid.)

If all possible in-band values are valid, you're stuck with an out-of-band flag as you mentioned.

摘星┃星的人 2025-01-12 01:38:17

CGPoint 的惰性计算可以通过(至少)两种不同的方式完成:

干净的方式是存储一个 BOOL,它保留您的 是否存在的信息。 CGPoint 已初始化。

@interface GraphView : UIView {
  BOOL _originInitialized;
}
@property (nonatomic) CGPoint origin;
@end

@implementation GraphView
@synthesize origin = _origin;

// extend the init methods
-(id) init {
  ...
  _originInitialized = NO;
  ...
}

- (CGPoint) origin {
    if (_originInitialized) {
         _origin = CGPointMake(self.bounds.origin.x + self.bounds.size.width/2, 
                               self.bounds.origin.y + self.bounds.size.height/2);
         _originInitialized = YES;
    }
    return _origin;
}
@end

如果您不想浪费BOOL内存,您可以采用肮脏的方法
并使用初始值来测试您的 _origin

@interface GraphView : UIView
@property (nonatomic) CGPoint origin;
@end

@implementation GraphView
@synthesize origin = _origin;

// extend the init methods
-(id) init {
  ...
  _origin = CGPointMake(-23.0, -42.0);
  ...
}

- (CGPoint) origin {
    if (_origin.x == -23.0 && _origin.y == -42.0) {
         _origin = CGPointMake(self.bounds.origin.x + self.bounds.size.width/2, 
                               self.bounds.origin.y + self.bounds.size.height/2);
    }
    return _origin;
}
@end

但我建议不要使用第二个。

The lazy evaluation of the CGPoint could be done in (at least) two different ways:

The clean way would be storing a BOOL, that keeps the information whether your CGPoint has been initialized.

@interface GraphView : UIView {
  BOOL _originInitialized;
}
@property (nonatomic) CGPoint origin;
@end

@implementation GraphView
@synthesize origin = _origin;

// extend the init methods
-(id) init {
  ...
  _originInitialized = NO;
  ...
}

- (CGPoint) origin {
    if (_originInitialized) {
         _origin = CGPointMake(self.bounds.origin.x + self.bounds.size.width/2, 
                               self.bounds.origin.y + self.bounds.size.height/2);
         _originInitialized = YES;
    }
    return _origin;
}
@end

In case you do not want to waste a BOOL of memory you could do a dirty approach
and use an initial value, to test your _origin against:

@interface GraphView : UIView
@property (nonatomic) CGPoint origin;
@end

@implementation GraphView
@synthesize origin = _origin;

// extend the init methods
-(id) init {
  ...
  _origin = CGPointMake(-23.0, -42.0);
  ...
}

- (CGPoint) origin {
    if (_origin.x == -23.0 && _origin.y == -42.0) {
         _origin = CGPointMake(self.bounds.origin.x + self.bounds.size.width/2, 
                               self.bounds.origin.y + self.bounds.size.height/2);
    }
    return _origin;
}
@end

But I'd recommend not to use the second one.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文