【问题标题】:Using Pointers safely in Objective-C在 Objective-C 中安全地使用指针
【发布时间】:2012-03-08 09:20:17
【问题描述】:

假设我有一个带有整数实例变量和 1 个成员函数的对象。该函数在单独的线程上运行,并不断更新实例变量的值。我有第二个函数(不同类的一部分),它也在一个单独的线程上运行,并且需要实时访问第一个对象中的整数实例变量。因此,我将指向实例变量的指针传递给第二个函数,而第二个函数只是取消引用该指针。这样,第二个函数始终可以访问实例变量的更新值。

但是,我不希望第二个函数能够更改实例变量的值。我希望它具有只读访问权限,但是由于我传递了一个指向实例变量的指针,它是否能够更改实例变量的值?如果是这样,我如何将指针取消引用限制为只读?如果这不可能,那么解决这个问题最安全的方法是什么?

Mac OS X 雪豹,Xcode 3.2.6。带有 Cocoa 的 Objective-C。

编辑:对不起,我忘了提到我不能使实例变量成为常量,因为我需要它所属的类才能修改它。如果我让它保持不变,它将完全限制对变量的写入。

【问题讨论】:

    标签: objective-c macos oop memory pointers


    【解决方案1】:

    您可以在此处使用类型系统。您可以使用const int *,而不是int*,这意味着它是一个指向常量int 的指针。可以通过在函数内部强制转换为 (int *) 来解决这个问题,但这违反了类型系统(因此是显式强制转换)并且行为良好的函数不会这样做。

    注意,如果您的函数需要确保它具有最新值,您可能还需要输入volatile。否则编译器可能会决定在某处缓存取消引用的结果。

    【讨论】:

    • 所以我需要调整函数的参数而不是变量本身对吗?
    • @Farhad:是的。该函数可以声明为void myfunc(const int *ptr),这意味着它声明它永远不会分配给取消引用的指针。
    • @Farhad:请参阅 man strcmp 以获得一个很好的例子。 strcmp() 将其参数声明为 const char *,因为它不会修改它们。
    【解决方案2】:

    正确的做法是让实例变量成为一个属性,并给第二个函数一个指向对象的指针而不是指向实例变量的指针。然后代码可以调用对象的属性访问器。目前尚不清楚您的代码是如何构造的,但也可以将属性设置为对类定义之外的方法为只读,对属于类的方法进行读写。

    最后,由于您从多个线程访问该属性,因此您需要提供某种同步以避免两个线程同时尝试访问该属性。最简单的方法是在属性声明中省略“非原子”(这是大多数人反射性地声明其属性的方式),这将导致属性访问器是原子的。第二种最简单的方法是使用@synchronized 指令。

    【讨论】:

    • 你实际上不能指定atomic,你可以省略nonatomic。另外,我不知道 OP 的用例是什么,但使用 @synchronized 可能太贵了。
    • @KevinBallard 我在想什么?! ;-) 谢谢。至于@synchronized,我并不反对,但我认为简单和缓慢工作比复杂而不工作或随机坏数据要好。
    猜你喜欢
    • 2012-02-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-29
    • 2011-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多