0

我将长话短说,并举一个我的问题的例子。

给定一个具有指向原始类型的指针作为属性的类:

@interface ClassOne : NSObject
{
int* aNumber
}

@property int* aNumber;

类被实例化,并且 aNumber 被分配并分配一个值,相应地:

ClassOne* bob = [[ClassOne alloc] init];
bob.aNumber = malloc(sizeof(int));
*bob.aNumber = 5;

然后通过引用传递它来分配此类类的单独实例的 aNumber 值,相应地:

ClassOne* fred = [[ClassOne alloc] init];
fred.aNumber = bob.aNumber;

然后 Fred 的 aNumber 指针被释放、重新分配并分配一个新值,例如 7。

现在,我遇到的问题;由于 Fred 被分配了与 Bob 相同的指针,我希望 Bob 的 aNumber 现在的值为 7。它没有,因为由于某种原因它的指针被释放,但没有重新分配(它仍然指向第一次分配的地址相同,现在已释放)。然而,Fred 的指针在不同的内存位置具有分配的值 7。

为什么会这样?我在误解什么?我怎样才能让它像 C++ 一样工作?

编辑:对,一个新鲜的早晨,我可以看到我举了一个非常糟糕的下午 5 点综合症的例子。我想要做的更像是这样的:

@interface classOne : NSObject
{
    int* numA;
}
@property int* numA;

@implementation...etc

numA 被分配并赋值。稍后,在一个单独的线程中(带有必要的锁等),这是完成的:

int* numB= malloc(sizeof(int));
*numB = 5;  
free(RefToClassOne.numA);
RefToClassOne.numA = numB;

numA 确实被释放,但没有被分配 numB 指向的值,这是我想要的行为。

更长的故事的一部分是它是传递给openGL的顶点缓冲区的一部分的顶点计数。我意识到它不应该是一个指针,但是坐标的 float* 缓冲区以相同的方式处理并且需要具有可变大小,所以我想解决这个问题也可以解决这个问题。

4

4 回答 4

3

What you are misunderstanding is that (a) you cannot pass things by reference in Objective-C, and (b) even if you could, it wouldn't help you here.

Objective-C only allows you to pass things by value. Sometimes, as in the case of objects or pointers, the value you are passing is itself a reference, but it's being treated as a value. C++-style transparent references don't exist.

But suppose that we had them. How would that help in this case? The aNumber instance variable is still of type int*; when you assign to it (as in fred.aNumber = bob.aNumber), you must create a copy. At this point, it doesn't matter what was passed by reference, and nor does it matter that things are instance variables. Your code is effectively the same as

int* bobNumber;
int* fredNumber;

bobNumber   = malloc(sizeof(int));
*bobNumber  = 5;
fredNumber  = bobNumber;

Here, bobNumber and fredNumber are different variables—they have different names, live at different locations in memory, etc.—that happen to have the same value. Now, the value they have is a reference to another location in memory, so they are equivalent references. However, what happens if we change one of them?

free(fredNumber);
fredNumber  = malloc(sizeof(int));
*fredNumber = 7;

Since function arguments are passed by value, free can't do anything to fredNumber itself; it can only operate on fredNumber's value, freeing the referenced memory. Since this is the same as bobNumber's value, we see this effect if we try to dereference bobNumber. Next, we assign a value to fredNumber. Since fredNumber and bobNumber live at different locations in memory, this assignment naturally does nothing to bobNumber. At this point, fredNumber != bobNumber, so naturally when we assign 7 to *fredNumber, nothing happens to *bobNumber (which is invalid anyway, having just been freed).

Note that your comment about "making it work like C++ does" is strange; C++, like I said, doesn't work this way either. If you really wanted to make this work in C++, you would have to have a reference instance variable

class ClassTwo {
  public:
    int*& aNumber;
    ClassTwo(int*& an) : aNumber(an) { }
};

Note that an needs to be passed by reference; I originally tried to do it without that, and then a copy was created in the constructor, producing the same old set of problems.

Now, whether or not we pass bob by reference, it will still have the same aNumber reference, so we can construct something like

int* shared;
ClassTwo bob(shared);
bob.aNumber = new int(5);
ClassTwo fred(bob.aNumber);
delete fred.aNumber;
fred.aNumber = new int(7);

And everything will work like you expect. However, this may well not be a good idea. For one reason why, note the shared variable—references need to be able to reference something. And this can produce problems: if the object being reference goes out of scope, the behavior of the reference is undefined.

于 2010-04-15T16:49:06.133 回答
0

这在 C++ 中的工作方式相同。这是一个等效的示例:

class Bob {
    public:
    int *aNumber;
};

void wontWork() {
    Bob bob, fred;
    bob.aNumber = new int;
    *bob.aNumber = 5;
    fred.aNumber = bob.aNumber;
    delete fred.aNumber;
    fred.aNumber = new int;
    *fred.aNumber = 7;
    cout << *bob.aNumber << *fred.aNumber << endl;
}

您希望 *bob.aNumber 在这里是 7 吗?当你这样做时delete fred.aNumber,这释放了 bob 和 fred 指向的内存。然后你重新分配了 fred 指向新的内存,但是你没有重新分配 bob,所以它只是一个悬空指针。所以没有什么会导致 bob 为 7。请记住,指针只是简单的值类型,如 int。没有什么魔法可以使指向同一地址的两个指针相互同步。

于 2010-04-15T17:05:16.587 回答
0

如果您将两者都设置为指向同一个对象,那么当您释放该对象时,您实际上是在删除两者都指向的内容,因此两个指针都变得无效。为了重新分配,您需要通过将两个指针设置为指向同一个新对象来重复相同的过程。

销毁一个对象不会自动更新指向它的所有指针,因为这些指针彼此独立并且彼此不知道任何信息。

你最好从原始创建一个克隆而不是共享有问题的对象,这样每个“aNumber”都指向它自己的副本。

我想你所追求的就像你写的 C++

弗雷德=鲍勃;

弗雷德在哪里创建了鲍勃的副本

在这种情况下,您将需要在您的课程中使用某种克隆功能。

编辑:改写

于 2010-04-15T16:08:04.860 回答
0

好吧,据我所知,您的代码完全按照您的要求执行。

使用指向 int 的指针并不是处理值最兼容的方式。您将需要适当地调用它,如果您只想在对象之间传递值,那么使用 NSValue 对象会更简单。

于 2010-04-15T16:38:01.813 回答